Gatling发送请求前如何读取请求体为字符串并签名XML
Fixing XML Signature Generation with Gatling's ElFileBody
I see the issue you're facing here - let's break down why your current approach isn't working and how to fix it properly.
Why Your Current Code Fails
The problem comes from misunderstanding how Gatling's ElFileBody and processRequestBody work together:
ElFileBodyreturns aTemplateBody, which is an expression (a function that takes aSessionand returns the rendered XML string after replacing variables like${seqNumber}).- When you call
body.toStringin yourprocessRequestBodylambda, you're just getting the string representation of theTemplateBodyobject itself (e.g.,io.gatling.http.request.body.TemplateBody@12345), not the actual rendered XML content. The variable replacement hasn't happened yet at this point.
Solution: Process the Rendered XML Content
We need to first get the fully rendered XML (with seqNumber replaced) before applying the signature. Here's the corrected approach:
Step-by-Step Fixed Code
during(100 seconds) { forever("seqNumber") { exec(http("Post New Document") .post("/document") .body(ElFileBody("bodies/document.xml")) // First process: render template, apply signature .processRequestBody { originalBody => // originalBody is an Expression[Session => String] Expression { session => // Execute the template to get the rendered XML with seqNumber replaced originalBody(session).map { renderedXml => // Apply your signature logic to the fully rendered XML signatureHelper.sign(renderedXml) } } } // Second process: gzip the signed XML .processRequestBody(gzipBody) .header("Content-Type", "application/xml") .header("Content-Encoding", "gzip") .check(status.not(400), status.not(500))) .exitHereIfFailed } }
Key Changes Explained
- Access the rendered XML: Instead of calling
body.toString, we useoriginalBody(session)to execute the template and get the actual XML string with${seqNumber}replaced by the current session value. - Handle Gatling's Validation type:
originalBody(session)returns aValidation[String](either aSuccesswith the XML or aFailureif rendering fails). We use.mapto safely process the successful case. - Preserve processing order: We first apply the signature to the uncompressed XML, then run
gzipBodyto compress the signed content - this ensures the signature is valid for the actual XML being sent (not the compressed version).
Alternative Approach: Pre-Load the Template
If you prefer, you can pre-load the XML template once at simulation startup, then render and sign it directly in a StringBody:
// Load the template once when the simulation starts val documentTemplate = scala.io.Source.fromFile("bodies/document.xml").mkString during(100 seconds) { forever("seqNumber") { exec(http("Post New Document") .post("/document") .body(StringBody(session => { // Replace seqNumber with the current session value val renderedXml = documentTemplate.replace("${seqNumber}", session("seqNumber").as[String]) // Sign the rendered XML signatureHelper.sign(renderedXml) })) .processRequestBody(gzipBody) .header("Content-Type", "application/xml") .header("Content-Encoding", "gzip") .check(status.not(400), status.not(500))) .exitHereIfFailed } }
This approach is more explicit and might be easier to debug if you need to inspect the rendered XML before signing.
Important Notes
- Ensure your
signatureHelper.signmethod correctly parses the input XML string, adds the<ds:Signature>element, and returns a valid XML string. - Double-check that the
seqNumbersession variable is being incremented correctly (yourforever("seqNumber")loop should handle this automatically, but it's worth verifying).
内容的提问来源于stack exchange,提问作者chomar.c
相关产品推荐
相关产品推荐

