scala - обрабатывает строку, полученную при анализе выражения EL, с помощью анонимной функции - PullRequest
0 голосов
/ 02 января 2019

Я использую выражение Gatling EL в http-тесте, и кажется, что перенос 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: пароль» и использовать его в качестве заголовка авторизации, с «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

Итак, это преобразование строки на месте, а не отображение коллекции.Что я могу сделать?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Нашел ответ на другой вопрос:

Использование фидера для передачи значений заголовка (Gatling)

Решение состоит в том, чтобы написать здесь функцию, в моем случае:

.header(HttpHeaderNames.Authorization, session =>
    for {
        username <- session("username").validate[String]
    } yield "AppBasic " + Base64.getEncoder.encodeToString((username + ":" + "1111").getBytes())
)

Спасибо за это.

До того, как я нашел это, я сделал обходной путь: руководитель группы заменил тестовый CSK в 10 тысяч строк на один из 20 строк, потому что Gatling заранее загрузит контент в память при тестировании, а большой CSV будет использовать память согласно документация.

Таким образом, используя 20 строк, я могу жестко закодировать закодированную электронную почту: пароль в файле csv и прочитать их с именем столбца "$ {col_name}".

Но лучше читать с сессии. Я этого не знал. Спасибо @ tilois.

0 голосов
/ 02 января 2019

Это больше проблема Гатлинга, чем проблема Скала, но давайте попробуем выяснить, что здесь происходит.

Интерполяция строки Scala

Чтобы включить значения в строку, можно использовать интерполяцию строк с использованием синтаксиса ${…}. Пример:

s"Hello, $name", где name = "World" приведет к "Hello World. Однако это , а не , что вы используете.

Теперь самое простое, что нужно сделать - это использовать это вместо этого. Однако для этого потребуется, чтобы значение username было доступно в программе scala.

Если я правильно понимаю, вы хотите, чтобы значение пришло из сеанса Gatling, и, следовательно, вы используете Язык выражений Gatling , как вы уже упоминали.

Если это не так, проще всего использовать интерполяцию строки 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

Что здесь происходит?

Гатлинг анализирует значения параметров Strings и превращает их в функции, которые будут вычислять результат на основе данных, сохраненных в сеансе, когда они будут оцениваться.

(взято из документации с подсветкой от меня) Это требует, чтобы строка была передана Гатлингу. Однако вы используете простой Scala для преобразования String. Gatling - это встроенный DSL, что означает, что он встроен в основной язык (Scala), и это вас просто поразило.

Вы делаете это

"${username}".map(username =>
    Base64.getEncoder().encodeToString((username + ":" + "password").getBytes()

Давайте пройдем этот шаг за шагом: ${username} - это , а не Строковая интерполяция, как описано выше, поскольку в начале отсутствуют «методы строковой интерполяции» (например, s в s""), что является правильным, если вы хотите передать его буквально для того, чтобы его проанализировал Гатлинг. Однако вы не передаете его Гатлингу, вместо этого вы 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, } в сочетании с немного большим.

Что можно сделать вместо этого, чтобы использовать пароль из сеанса

Проще всего было бы использовать то, что Гатлинг уже предлагает . Они не знают о вашем AppBasic и будут использовать Basic вместо этого ... так что никакой опции.

Вы можете использовать Session API для доступа к значению (с session("name") доступом к значению из сеанса).

.header(HttpHeaderNames.Authorization, s"AppBasic ${asBase64(s"${session("username").as[String]}:$password")}")

, что предполагает, что функция asBase64 определена, как указано выше (в противном случае она немного длиннее), и в области видимости есть переменная password. Если не просто замените его (вместе с долларом) на значение, которое вы хотите там.

Так что, надеюсь, это поможет вам с вашей проблемой. Я бы сказал, что вы не до конца понимаете, что конкретно относится к Гатлингу и что такое Скала (что совершенно нормально, но иногда это вас укусит, как здесь). Я пошел немного дальше в надежде, что это немного разделит его.

Ваша основная проблема заключалась в том, что вы использовали доступ к значениям из сеанса с долларовой нотацией. Что хорошо, если вы передаете значения Гатлингу. В этом случае Гатлинг сделает это за вас. Однако это не будет работать в простом Scala, там вы должны получить к ним доступ, используя Session API. Вы можете увидеть, можете ли вы получить доступ к значению с помощью долларовой нотации, если API говорит о Expression[…], что означает, что Гатлингу требуется дополнительный ход для его анализа (именно поэтому он знает, что в нем есть ссылка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...