我在http测试中使用了加特林EL表达式,看来包装任何形式的EL表达式都会使解析无效,即
这有效:
def run(env: Parameters): ChainBuilder =
feed(env.feeder)
.exec(
http(Seq(env.env, "verify").mkString(":"))
.get(env.base + "/verify")
.queryParam("email", "${username}")
.check(
status.is(200),
jsonPath("$..exist").is("true"),
)
)
exitHereIfFailed
但这不起作用:
def run(env: Parameters): ChainBuilder =
feed(env.feeder).exec(
http(Seq(env.base, "authorize").mkString(":"))
.post(env.base + "/authorize")
.asJSON // "Accept" and "ContentType" set to JSON
.header(HttpHeaderNames.AcceptCharset, "UTF-8")
.header(HttpHeaderNames.Authorization,
"AppBasic " + Base64.getEncoder().encodeToString(("${username}" + ":" + "password").getBytes())))
.body(StringBody(env.authorizeBody))
.check(
status.is(200),
header(HttpHeaderNames.ContentType).is(HttpHeaderValues.ApplicationJson),
header(HttpHeaderNames.AcceptCharset).is("UTF-8"),
jsonPath("$..id_token") exists
)
)
我想使用Base64“ email:password”进行编码,并将其用作授权标头,并以“ AppBasic”作为前缀。因此,不是Basic
授权,它以Basic
作为前缀。
现在我做类似的事情:
...
.header(HttpHeaderNames.Authorization,
"AppBasic " + "${username}".map(username => Base64.getEncoder().encodeToString((username + ":" + "password").getBytes())))
...
但是,日志显示了一个奇怪的Vector
。我想要一个String
。
HTTP request:
POST <some url>
headers=
Accept: application/json
Content-Type: application/json
Accept-Charset: UTF-8
Authorization: AppBasic Vector(JDoxMTEx, ezoxMTEx, dToxMTEx, czoxMTEx, ZToxMTEx, cjoxMTEx, bjoxMTEx, YToxMTEx, bToxMTEx, ZToxMTEx, fToxMTEx)
User-Agent: curl/7.54.0
Content-Length: 143
因此,它是就地字符串转换,而不是集合映射。我该怎么办?
答案 0 :(得分:1)
这比Scala问题更像是加特林问题,但让我们尝试找出这里发生的情况。
要将值包含在字符串中,可以使用${…}
语法使用字符串插值。示例:
s"Hello, $name"
,其中name = "World"
将产生"Hello World
。但是,这不是您正在使用的内容。
现在最简单的方法是实际使用它。但是,它将需要在scala程序中使用username
的值。
如果我没看错的话,您希望该值来自“加特林会话”,因此您正在使用Gatling Expression Language,就像您已经提到的那样。
如果不是这种情况,最简单的方法是使用Scala字符串插值:
def asBase64(input: String): String = java.util.Base64.getEncoder().encodeToString(input.getBytes())
val username = "johnDoe"
val password = "1111" // Some more or less random password
val headerValue = asBase64(s"${username}:$password")
val header = s"Basic $headerValue" // … should be "Basic am9obkRvZToxMTEx" here
加特林(Gatling)解析字符串参数值,并将其转换为函数,该函数将在评估它们时基于存储在Session中的数据来计算结果。
(摘自文档,重点是我) 这要求将字符串传递给Gatling。但是,您在此处使用普通的Scala来转换String。 Gatling是嵌入式DSL,这意味着它嵌入在主机语言(Scala)中,这对您来说只是一个问题。
您正在这样做
"${username}".map(username =>
Base64.getEncoder().encodeToString((username + ":" + "password").getBytes()
让我们逐步进行以下操作:
${username}
不是上面的 字符串插值,因为它开头缺少“字符串插值方法”(例如s
中的s""
),这是正确的,如果您想按字面传递它,以供Gatling解析。
但是,您不会将其传递给加特林,而是map
。
这是普通的Scala,而Scala根本不知道其中包含值的Session
之类的东西。
相反,String.map
传递每个字符并在其上使用函数。
您认为username
实际上就是一个字母。
因此,它继续进行并且在每个字母上使用username + ":" + "password"
。
顺便说一句:您的原始代码中没有"password"
…并且,如果这是一个真正的隐藏密码,那么它将不再被隐藏(Base64是可逆的)。
这就是这里
Vector(JDoxMTEx, ezoxMTEx, dToxMTEx, czoxMTEx, ZToxMTEx, cjoxMTEx, bjoxMTEx, YToxMTEx, bToxMTEx, ZToxMTEx, fToxMTEx)
来自。它有11个条目,$, {, u, s, e, r, n, a, m, e, }
中的每个字母一个,再加上一点。
最简单的方法是使用Gatling already offers。这些人不知道您的AppBasic
,而是使用Basic
……所以没有选择。
您可以使用Session API来访问值(session("name")
从会话中访问值)。
.header(HttpHeaderNames.Authorization, s"AppBasic ${asBase64(s"${session("username").as[String]}:$password")}")
假定函数asBase64
的定义如上(否则,它会更长一些),并且作用域中有一个变量password
。
如果不是这样,只需将它(连同美元)替换为您想要的值即可。
因此希望这可以帮助您解决问题。 我要说的是,您还不完全了解Gatling的特定功能和Scala的功能(这完全可以,但有时会像这里一样咬住您)。我花了一些时间,希望这能使两者分开。
您的基本问题是,您习惯于使用美元符号访问会话中的值。只要将值传递给加特林,就可以了。在这种情况下,加特林可以为您完成此任务。但是,它不能在普通的Scala中工作,您必须使用Session API访问它们。您可以查看是否可以使用美元符号访问值,如果API讨论了Expression[…]
,这意味着加特林需要额外的时间来解析它(这就是为什么它知道其中包含引用的原因) )
答案 1 :(得分:0)
找到了另一个问题的答案:
Using a feeder to pass in header values (Gatling)
解决方案是在我的情况下在此处编写一个函数:
.header(HttpHeaderNames.Authorization, session =>
for {
username <- session("username").validate[String]
} yield "AppBasic " + Base64.getEncoder.encodeToString((username + ":" + "1111").getBytes())
)
谢谢。
在发现此问题之前,我已经采取了一种变通方法:团队负责人将20k行的csv替换为10k行的csv,因为加特林将事先将内容加载到测试中的内存中,并且较大的csv将消耗内存文档。
因此,只要20行,我就可以在csv文件中对编码的email:password进行硬编码,并以列名“ $ {col_name}”读取它们。
但是最好从会话中阅读。我不知道谢谢@tilois。