簡體   English   中英

Gatling:對HTML響應中隱藏的一些JSON執行檢查

[英]Gatling: execute a check on some JSON hidden inside an HTML response

在加特林,我想對HTML響應中包含的一些JSON進行檢查,如下所示:

<!doctype html>
<html lang="fr">
  <head>
    <script>
      var documentLoaded = performance.now();
    </script>
    <link rel="stylesheet" href="/styles/main.f14d8fab5a7e.css">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
    <link rel="manifest" href="/manifest.json">
    <link rel="preconnect" href="https://www.gstatic.com">

    <title data-react-helmet="true">Asus Discount</title>
    <meta data-react-helmet="true" name="description" content="Asus discount”/><meta data-react-helmet="true" name="keywords" content="Asus"/>

  </head>
  <body>
  <div>Some content</div>

  <script>
      var parseStart = performance.now();
  </script>

  <script>
    window.__INITIAL_STATE__ = {some JSON}; <!-- This is what I need -->
    window.__ENV_VARIABLES__ = {some other JSON};
    window.renderTime = '76';
    window.fetchTime = '349';
  </script>
  <script type="text/javascript" charset="utf-8" src="/vendor.e33d9940372.js"></script>
  <script type="application/ld+json" src="/schema.fr.json"></script>
  </body>
</html>

我的實際解決方案(正在運行)如下所示:

def loadPageJsonInHTML(requestName: String, link: String): ChainBuilder ={
  exec(
    http(requestName)
      .get(link)
      .check(regex("""window[.]__INITIAL_STATE__ = ([^;]+)""").find.transform(s => parseSToProdList(s)).saveAs("prod_list")
      )
  )
  doIf("${prod_list.size()}" == 0){
    exec{session => session.markAsFailed}
  }
}

def parseSToProdList(jsonString: String): Seq[String] ={
  val jsonMap = jsonStrToMap(jsonString)
  val buffer = mutable.Buffer.empty[String]
  jsonMap("products").asInstanceOf[Map[String, Any]].foreach{f =>
    if(f._2.asInstanceOf[Map[String, Any]].keySet.exists(_ == "code"))
      buffer.append(f._2.asInstanceOf[Map[String, Any]]("code").asInstanceOf[String])
  }
  buffer.toSeq
}

def jsonStrToMap(jsonStr: String): Map[String, Any] = {
  implicit val formats = org.json4s.DefaultFormats
  parse(jsonStr).extract[Map[String, Any]]
}

但是,這種解決方案有幾個缺點:

  1. 只要找到正則表達式並且不關心JSON中是否有任何產品,檢查將始終成功 - >我必須稍后手動檢查它;
  2. 具有提取所需數據的函數比使用像“$ .products。* .code”這樣的Json Path表達式更難以維護,該表達式可以存儲在集中路徑文件中以便於維護;
  3. 這是我必須使用轉換來檢查請求的JSON,使其更難以閱讀和理解的地方。

我想要實現的是看起來像這樣的東西:

def loadPageJsonInHTML(requestName: String, link: String): ChainBuilder ={
  exec(
    http(requestName)
      .get(link)
      .check(jsonPath("""$.products.*.code""").findAll.saveAs("prod_list")
  )

要么

def loadPageJsonInHTML(requestName: String, link: String): ChainBuilder ={
  exec(
    http(requestName)
      .get(link)
      .check(jsonpJsonPath("""$.products.*.code""").findAll.saveAs("prod_list")
  )

當然,jsonPath不起作用,因為大部分答案都是HTML。 jsonpJsonPath不起作用,因為響應中有幾個Json字符串。

關於如何在避免某些HTML上的正則表達式的同時更好地(並且很好地)做到這一點的任何好的輸入? 提前致謝

因此,經過一些挖掘后,我找到了一個使用“.transformResponse”的解決方法,以便在實際檢查之前提取字符串,為其提供一個可在Json中解析的默認值。 然后,為了確保我們確實找到了正則表達式,我們確保它不是我們的默認值:

  def loadPageJsonInHTML(requestName: String, link: String): ChainBuilder = {
    exec(
      http(requestName)
        .get(link)
        .transformResponse{(session, response) =>
          response.copy(body = new StringResponseBody(
              (for(m <- """window[.]__INITIAL_STATE__ = ([^;]+)""".r
                           .findFirstMatchIn(response.body.string)
                  ) yield m.group(1)
              ).getOrElse("""{"error":"chain not found"}"""),
              UTF_8
            )
          )
        }
        .check(bodyString.not("""{"error":"chain not found"}"""))
        .check(jsonPath("""$.products.*.code""").findAll.saveAs("prod_list")
        )
    )
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM