HTTP Request

How to craft HTTP requests, including HTTP method like GET or POST, HTTP headers, query parameters, form parameters, body and checks.

Request name

HTTP support has a dedicated DSL, whose entry point is the http(requestName) method.

This request name is important because it will act as a key when computing stats for the reports. If the same name appears in multiple places in a Simulation, Gatling will consider the requests to be the same type, and their statistics will be aggregated.

       
// with a static value
http("requestName").get("https://gatling.io");
// with a dynamic value computed from a Gatling Expression Language String
http("#{requestName}").get("https://gatling.io");
// a dynamic value computed from a function
http(session -> session.getString("requestName")).get("https://gatling.io");
// with a static value
http("requestName").get("https://gatling.io");
// with a dynamic value computed from a Gatling Expression Language String
http("#{requestName}").get("https://gatling.io");
// a dynamic value computed from a function
http((session) => session.get("requestName")).get("https://gatling.io");
// with a static value
http("requestName").get("https://gatling.io")
// with a dynamic value computed from a Gatling Expression Language String
http("#{requestName}").get("https://gatling.io")
// with a dynamic value computed from a function
http { session -> session.getString("requestName") }.get("https://gatling.io")
// with a static value
http("requestName").get("https://gatling.io")
// with a dynamic value computed from a Gatling Expression Language String
http("#{requestName}").get("https://gatling.io")
// with a dynamic value computed from a function
http(session => session("requestName").as[String]).get("https://gatling.io")

HTTP requests must be passed to the exec() method to be attached to the scenario and executed.

       
// inline style
scenario("scenarioName")
  .exec(http("requestName").get("url"));

// non inline style
HttpRequestActionBuilder request = http("RequestName").get("url");

scenario("MyScenario")
  .exec(request);
// inline style
scenario("scenarioName")
  .exec(http("requestName").get("url"));

// non inline style
const request = http("RequestName").get("url");

scenario("MyScenario")
  .exec(request);
// inline style
scenario("scenarioName")
  .exec(http("requestName").get("url"))

// non inline style
val request = http("RequestName").get("url")

scenario("MyScenario")
  .exec(request)
// inline style
scenario("ScenarioName")
  .exec(http("RequestName").get("url"))

// non inline style
val request = http("RequestName").get("url")

scenario("ScenarioName")
  .exec(request)

Method and URL

Gatling provides built-ins for the most common methods. Those are simply the method name in minor case.

       
// with an absolute static url
http("name").get("https://gatling.io");
// with a dynamic value computed from a Gatling Expression Language String
http("name").get("#{url}");
// a dynamic value computed from a function
http("name").get(session -> session.getString("url"));

http("name").put("https://gatling.io");
http("name").post("https://gatling.io");
http("name").delete("https://gatling.io");
http("name").head("https://gatling.io");
http("name").patch("https://gatling.io");
http("name").options("https://gatling.io");
http("name").httpRequest("PURGE", "http://myNginx.com");
// with an absolute static url
http("name").get("https://gatling.io");
// with a dynamic value computed from a Gatling Expression Language String
http("name").get("#{url}");
// a dynamic value computed from a function
http("name").get((session) => session.get("url"));

http("name").put("https://gatling.io");
http("name").post("https://gatling.io");
http("name").delete("https://gatling.io");
http("name").head("https://gatling.io");
http("name").patch("https://gatling.io");
http("name").options("https://gatling.io");
http("name").httpRequest("PURGE", "http://myNginx.com");
// with an absolute static url
http("name").get("https://gatling.io")
// with a dynamic value computed from a Gatling Expression Language String
http("name").get("#{url}")
// with a dynamic value computed from a function
http("name").get { session -> session.getString("url") }

http("name").put("https://gatling.io")
http("name").post("https://gatling.io")
http("name").delete("https://gatling.io")
http("name").head("https://gatling.io")
http("name").patch("https://gatling.io")
http("name").options("https://gatling.io")
http("name").httpRequest("PURGE", "http://myNginx.com")
// with an absolute static url
http("name").get("https://gatling.io")
// with a dynamic value computed from a Gatling Expression Language String
http("name").get("#{url}")
// with a dynamic value computed from a function
http("name").get(session => session("url").as[String])

http("name").put("https://gatling.io")
http("name").post("https://gatling.io")
http("name").delete("https://gatling.io")
http("name").head("https://gatling.io")
http("name").patch("https://gatling.io")
http("name").options("https://gatling.io")
http("name").httpRequest("PURGE", "http://myNginx.com")

Query parameters

Frameworks and developers often pass additional information in the query, which is the part of the URL after the ?. A query is composed of key=value pairs, separated by &. Those are named query parameters.

For example, https://github.com/gatling/gatling/issues?milestone=1&state=open contains 2 query parameters:

  • milestone=1 : the key is milestone and its value is 1
  • state=open : the key is state and its value is open

To set the query parameters of an HTTP request, you can:

  • either pass the full query in the URL, e.g.:
       
http("Issues")
  .get("https://github.com/gatling/gatling/issues?milestone=1&state=open");
http("Issues")
  .get("https://github.com/gatling/gatling/issues?milestone=1&state=open");
http("Issues")
  .get("https://github.com/gatling/gatling/issues?milestone=1&state=open")
http("Issues")
  .get("https://github.com/gatling/gatling/issues?milestone=1&state=open")
  • or pass query parameters one by one to the method named queryParam:
       
// with static values
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "1")
  .queryParam("state", "open");

// with Gatling EL strings
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "#{milestoneValue}")
  .queryParam("state", "#{stateValue}");

// with functions
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", session -> session.getString("milestoneValue"))
  .queryParam("state", session -> session.getString("stateValue"));
// with static values
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "1")
  .queryParam("state", "open");

// with Gatling EL strings
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "#{milestoneValue}")
  .queryParam("state", "#{stateValue}");

// with functions
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", (session) => session.get("milestoneValue"))
  .queryParam("state", (session) => session.get("stateValue"));
// with static values
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "1")
  .queryParam("state", "open")

// with Gatling EL strings
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "#{milestoneValue}")
  .queryParam("state", "#{stateValue}")

// with functions
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone") { session -> session.getString("milestoneValue") }
  .queryParam("state") { session -> session.getString("stateValue") }
// with static values
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "1")
  .queryParam("state", "open")

// with Gatling EL strings
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", "#{milestoneValue}")
  .queryParam("state", "#{stateValue}")

// with functions
http("Issues").get("https://github.com/gatling/gatling/issues")
  .queryParam("milestone", session => session("milestoneValue").as[String])
  .queryParam("state", session => session("stateValue").as[String])

You can use multivaluedQueryParam to set query parameters with multiple values:

       
http("name").get("/")
  // with static values
  .multivaluedQueryParam("param", List.of("value1", "value2"));

http("name").get("/")
  // with a Gatling EL string pointing to a List
  .multivaluedQueryParam("param", "#{values}");

http("name").get("/")
  // with a function
  .multivaluedQueryParam("param", session -> List.of("value1", "value2"));
http("name").get("/")
  // with static values
  .multivaluedQueryParam("param", ["value1", "value2"]);

http("name").get("/")
  // with a Gatling EL string pointing to a List
  .multivaluedQueryParam("param", "#{values}");

http("name").get("/")
  // with a function
  .multivaluedQueryParam("param", (session) => ["value1", "value2"]);
http("name").get("/")
  // with static values
  .multivaluedQueryParam("param", listOf("value1", "value2"))

http("name").get("/")
  // with a Gatling EL string pointing to a List
  .multivaluedQueryParam("param", "#{values}")

http("name").get("/")
  // with a function
  .multivaluedQueryParam("param") { session -> listOf("value1", "value2") }
http("name").get("/")
  // with static values
  .multivaluedQueryParam("param", Seq("value1", "value2"))

http("name").get("/")
  // with a Gatling EL string pointing to a Seq
  .multivaluedQueryParam("param", "#{values}")

http("name").get("/")
  // with a function
  .multivaluedQueryParam("param", session => Seq("value1", "value2"))

You can use queryParamSeq and queryParamMap to set multiple query parameters at once:

       
http("name").get("/")
  .queryParamSeq(List.of(
      Map.entry("key1", "value1"),
      Map.entry("key2", "value2")
    )
  );

Map<String, Object> params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "value2");

http("name").get("/")
  .queryParamMap(params);
// queryParamSeq isn't implemented in Gatling JS, use queryParamMap:

const params = {
  "key1": "value1",
  "key2": "value2"
};

http("name").get("/")
  .queryParamMap(params);
http("name").get("/")
  .queryParamSeq(listOf(
    AbstractMap.SimpleEntry<String, Any?>("key1", "value1"),
    AbstractMap.SimpleEntry<String, Any?>("key2", "value2")
  ))

val params = mapOf(
  "key1" to "value1",
  "key2" to "value2"
)

http("name").get("/")
  .queryParamMap(params)
http("name").get("/")
  .queryParamSeq(Seq(("key1", "value1"), ("key2", "value2")))

http("name").get("/")
  .queryParamMap(Map("key1" -> "value1", "key2" -> "value2"))

Headers

The HTTP protocol uses headers to exchange information between the client and server that is not part of the message body.

Gatling HTTP allows you to specify any header you want with the header and headers methods.

       
// Extracting a map of headers allows you to reuse these in several requests
Map<String, String> sentHeaders = new HashMap<>();
    sentHeaders.put("content-type", "application/javascript");
    sentHeaders.put("accept", "text/html");

http("name").get("/")
  // Adds several headers at once
  .headers(sentHeaders)
  // Adds another header to the request
  .header("keep-alive", "150")
  // Overrides the content-type header
  .header("content-type", "application/json");
// Extracting a map of headers allows you to reuse these in several requests
const sentHeaders = {
  "content-type": "application/javascript",
  "accept": "text/html"
}

http("name").get("/")
  // Adds several headers at once
  .headers(sentHeaders)
  // Adds another header to the request
  .header("keep-alive", "150")
  // Overrides the content-type header
  .header("content-type", "application/json");
// Extracting a map of headers allows you to reuse these in several requests
val sentHeaders = mapOf(
  "content-type" to "application/javascript",
  "accept" to "text/html"
)

http("name").get("/")
  // Add several headers at once
  .headers(sentHeaders)
  // Adds another header to the request
  .header("keep-alive", "150")
  // Overrides the content-type header
  .header("content-type", "application/json")
// Extracting a map of headers allows you to reuse these in several requests
val sentHeaders = Map(
  "content-type" -> "application/javascript",
  "accept" -> "text/html"
)

http("name").get("/")
  // Adds several headers at once
  .headers(sentHeaders)
  // Adds another header to the request
  .header("keep-alive", "150")
  // Overrides the content-type header
  .header("content-type", "application/json")

asXXX

Gatling provides some handy shortcuts for setting the required headers for JSON, XML, and form encodings:

       
// asJson
http("name").post("/")
  .asJson();
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/json")
  // only for requests that have a body
  .header("content-type", "application/json");

// asXml
http("name").post("/")
  .asXml();
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/xhtml+xml")
  // only for requests that have a body
  .header("content-type", "application/xhtml+xml");

// asFormUrlEncoded
http("name").post("/")
  .asFormUrlEncoded();
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "application/application/x-www-form-urlencoded");

// asMultipartForm
http("name").post("/")
  .asMultipartForm();
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "multipart/form-data");
// asJson
http("name").post("/")
  .asJson();
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/json")
  // only for requests that have a body
  .header("content-type", "application/json");

// asXml
http("name").post("/")
  .asXml();
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/xhtml+xml")
  // only for requests that have a body
  .header("content-type", "application/xhtml+xml");

// asFormUrlEncoded
http("name").post("/")
  .asFormUrlEncoded();
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "application/application/x-www-form-urlencoded");

// asMultipartForm
http("name").post("/")
  .asMultipartForm();
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "multipart/form-data");
// asJson
http("name").post("/")
  .asJson()
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/json")
  // only for requests that have a body
  .header("content-type", "application/json")

// asXml
http("name").post("/")
  .asXml()
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/xhtml+xml")
  // only for requests that have a body
  .header("content-type", "application/xhtml+xml")

// asFormUrlEncoded
http("name").post("/")
  .asFormUrlEncoded()
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "application/application/x-www-form-urlencoded")

// asMultipartForm
http("name").post("/")
  .asMultipartForm()
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "multipart/form-data")
// asJson
http("name").post("/")
  .asJson
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/json")
  // only for requests that have a body
  .header("content-type", "application/json")

// asXml
http("name").post("/")
  .asXml
// is a shortcut for:
http("name").post("/")
  .header("accept", "application/xhtml+xml")
  // only for requests that have a body
  .header("content-type", "application/xhtml+xml")

// asFormUrlEncoded
http("name").post("/")
  .asFormUrlEncoded
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "application/application/x-www-form-urlencoded")

// asMultipartForm
http("name").post("/")
  .asMultipartForm
// is a shortcut for:
http("name").post("/")
  // only for requests that have a body
  .header("content-type", "multipart/form-data")

For a given request, you can also disable shared HttpProtocol headers with ignoreProtocolHeaders.

       
http("name").get("/")
  .ignoreProtocolHeaders();
http("name").get("/")
  .ignoreProtocolHeaders();
http("name").get("/")
  .ignoreProtocolHeaders()
http("name").get("/")
  .ignoreProtocolHeaders

Checks

You can add checks on a request.

       
http("name").get("/")
  .check(status().is(200));
http("name").get("/")
  .check(status().is(200));
http("name").get("/")
  .check(status().shouldBe(200))
http("name").get("/")
  .check(status.is(200))

For more information, see the HTTP Checks reference section.

For a given request, you can also disable common checks that were defined on the HttpProtocol with ignoreProtocolChecks:

       
http("name").get("/")
  .ignoreProtocolChecks();
http("name").get("/")
  .ignoreProtocolChecks();
http("name").get("/")
  .ignoreProtocolChecks()
http("name").get("/")
  .ignoreProtocolChecks

Request body

Full body

In this section, you can find the various methods for setting the full request body.

You can add a full body to an HTTP request with the dedicated method body, where body can be:

StringBody

StringBody lets you pass a text payload defined in your code. The charset used for writing the bytes on the wire is the one defined in the charset attribute of the Content-Type request header if defined; otherwise the one defined in gatling.conf is used.

This solution is typically used with Strings in the Gatling Expression Language format.

It takes one single parameter:

  • string the text content can be a plain String, a Gatling Expression Language String, or a function.
       
// with a static payload
http("name").post("/")
  .body(StringBody("{ \"foo\": \"staticValue\" }"));

// with a Gatling EL string payload
http("name").post("/")
  .body(StringBody("{ \"foo\": \"#{dynamicValue}\" }"));

// with a function payload
http("name").post("/")
  .body(StringBody(session -> "{ \"foo\": \"" + session.getString("dynamicValueKey") + "\" }"));
// with a static payload
http("name").post("/")
  .body(StringBody("{ \"foo\": \"staticValue\" }"));

// with a Gatling EL string payload
http("name").post("/")
  .body(StringBody("{ \"foo\": \"#{dynamicValue}\" }"));

// with a function payload
http("name").post("/")
  .body(StringBody((session) => `{ "foo": "${session.get("dynamicValueKey")}" }`));
// with a static payload
http("name").post("/")
  .body(StringBody("""{ "foo": "staticValue" }"""))

// with a Gatling EL string payload
http("name").post("/")
  .body(StringBody("""{ "foo": "#{dynamicValue}" }"""))

// with a function payload
http("name").post("/")
  .body(StringBody { session -> """{ "foo": "${session.getString("dynamicValueKey")}" }""" })
// with a static payload
http("name").post("/")
  .body(StringBody("""{ "foo": "staticValue" }"""))

// with a Gatling EL string payload
http("name").post("/")
  .body(StringBody("""{ "foo": "#{dynamicValue}" }"""))

// with a function payload
http("name").post("/")
  .body(StringBody(session => s"""{ "foo": "${session("dynamicValueKey").as[String]}" }"""))

Using a function is one way to craft complex dynamic payloads, as you can code your own logic.

       
static final class Templates {
  public static final Function<Session, String> template = session -> {
    String foo = session.getString("foo");
    String bar = session.getString("bar");
    return "{ \"foo\": \"" + foo + "\", \"bar\": \"" + bar + "\" }";
  };
}

http("name").post("/")
  .body(StringBody(Templates.template));
const template = (session) => {
  const foo = session.get("foo");
  const bar = session.get("bar");
  return `"{ "foo": "${foo}", "bar": "${bar}" }`;
};

http("name").post("/")
  .body(StringBody(template));
internal object Templates {
  val template = Function { session: Session ->
    val foo = session.getString("foo")
    val bar = session.getString("bar")
    """{ "foo": "$foo", "bar": "$bar" }"""
  }
}

  http("name").post("/")
    .body(StringBody(HttpRequestSampleJava.Templates.template))
object Templates {
  val template: Expression[String] = session =>
    for {
      foo <- session("foo").validate[String]
      bar <- session("bar").validate[String]
    } yield s"""{ "foo": "$foo", "bar": "$bar" }"""
}

http("name").post("/")
  .body(StringBody(Templates.template))

RawFileBody

RawFileBody lets you pass a raw file whose bytes will be sent as is, meaning it can be binary content. This way is the most efficient one as bytes can be cached and don’t have to be decoded into text and then re-encoded back into bytes to be written on the wire.

It takes one single parameter:

  • filePath the file location, can be a plain String, a Gatling Expression Language String, or a function.
       
// with a static path
http("name").post("/")
  .body(RawFileBody("rawPayload.json"));

// with a Gatling EL String path
http("name").post("/")
  .body(RawFileBody("#{payloadPath}"));

// with a function path
http("name").post("/")
  .body(RawFileBody(session -> session.getString("payloadPath")));
// with a static path
http("name").post("/")
  .body(RawFileBody("rawPayload.json"));

// with a Gatling EL String path
http("name").post("/")
  .body(RawFileBody("#{payloadPath}"));

// with a function path
http("name").post("/")
  .body(RawFileBody((session) => session.get("payloadPath")));
// with a static path
http("name").post("/")
  .body(RawFileBody("rawPayload.json"))

// with a Gatling EL String path
http("name").post("/")
  .body(RawFileBody("#{payloadPath}"))

// with a function path
http("name").post("/")
  .body(RawFileBody { session -> session.getString("payloadPath") })
// with a static path
http("name").post("/")
  .body(RawFileBody("rawPayload.json"))

// with a Gatling EL String path
http("name").post("/")
  .body(RawFileBody("#{payloadPath}"))

// with a function path
http("name").post("/")
  .body(RawFileBody(session => session("payloadPath").as[String]))

ElFileBody

ElFileBody lets you pass some text content resolved from a template file in the Gatling Expression Language format.

It takes one single parameter:

  • filePath the file location, can be a plain String, a Gatling Expression Language String, or a function.

Since Gatling EL is a text-based templating engine, content can not be non-textual.

       
http("name").post("/")
  .body(ElFileBody("rawPayload.json"));

// with a Gatling EL String path
http("name").post("/")
  .body(ElFileBody("#{payloadPath}"));

// with a function path
http("name").post("/")
  .body(ElFileBody(session -> session.getString("payloadPath")));
http("name").post("/")
  .body(ElFileBody("rawPayload.json"));

// with a Gatling EL String path
http("name").post("/")
  .body(ElFileBody("#{payloadPath}"));

// with a function path
http("name").post("/")
  .body(ElFileBody((session) => session.get("payloadPath")));
http("name").post("/")
  .body(ElFileBody("rawPayload.json"))

// with a Gatling EL String path
http("name").post("/")
  .body(ElFileBody("#{payloadPath}"))

// with a function path
http("name").post("/")
  .body(ElFileBody { session -> session.getString("payloadPath") })
http("name").post("/")
  .body(ElFileBody("rawPayload.json"))

// with a Gatling EL String path
http("name").post("/")
  .body(ElFileBody("#{payloadPath}"))

// with a function path
http("name").post("/")
  .body(ElFileBody(session => session("payloadPath").as[String]))

PebbleStringBody

Gatling Expression Language is definitively the most optimized templating engine for Gatling in terms of raw performance. However, it’s a bit limited in terms of logic you can implement in there. If you want loops and conditional blocks, you can use Gatling’s Pebble based templating engine.

       
http("name").post("/")
  .body(PebbleStringBody("{ \"foo\": \"{% if someCondition %}{{someValue}}{% endif %}\" }"));
http("name").post("/")
  .body(PebbleStringBody("{ \"foo\": \"{% if someCondition %}{{someValue}}{% endif %}\" }"));
http("name").post("/")
  .body(PebbleStringBody("{ \"foo\": \"{% if someCondition %}{{someValue}}{% endif %}\" }"))
http("name").post("/")
  .body(PebbleStringBody("""{ "foo": "{% if someCondition %}{{someValue}}{% endif %}" }"""))

PebbleFileBody

PebbleFileBody lets you pass the path to a Pebble file template.

       
// with a static value path
http("name").post("/")
  .body(PebbleFileBody("pebbleTemplate.json"));

// with a Gatling EL string path
http("name").post("/")
  .body(PebbleFileBody("#{templatePath}"));

// with a function path
http("name").post("/")
  .body(PebbleFileBody(session -> session.getString("templatePath")));
// with a static value path
http("name").post("/")
  .body(PebbleFileBody("pebbleTemplate.json"));

// with a Gatling EL string path
http("name").post("/")
  .body(PebbleFileBody("#{templatePath}"));

// with a function path
http("name").post("/")
  .body(PebbleFileBody((session) => session.get("templatePath")));
// with a static value path
http("name").post("/")
  .body(PebbleFileBody("pebbleTemplate.json"))

// with a Gatling EL string path
http("name").post("/")
  .body(PebbleFileBody("#{templatePath}"))

// with a function path
http("name").post("/")
  .body(PebbleFileBody { session -> session.getString("templatePath") })
// with a static value path
http("name").post("/")
  .body(PebbleFileBody("pebbleTemplate.json"))

// with a Gatling EL string path
http("name").post("/")
  .body(PebbleFileBody("#{templatePath}"))

// with a function path
http("name").post("/")
  .body(PebbleFileBody(session => session("templatePath").as[String]))

ByteArrayBody

ByteArrayBody lets you pass an array of bytes, typically when you want to use a binary protocol such as Protobuf.

       
// with a static value
http("name").post("/")
  .body(ByteArrayBody(new byte[] { 0, 1, 5, 4 }));

// with a static value
http("name").post("/")
  .body(ByteArrayBody("#{bytes}"));

// with a function
http("name").post("/")
  .body(ByteArrayBody(session ->
    Base64.getDecoder().decode(session.getString("data")))
  );
// with a static value
http("name").post("/")
  .body(ByteArrayBody([ 0, 1, 5, 4 ]));

// with a static value
http("name").post("/")
  .body(ByteArrayBody("#{bytes}"));

// with a function
http("name").post("/")
  .body(ByteArrayBody((session) => {
    // requires the "base-64" package
    const encoded = base64.encode(session.get("data"));
    const bytes = [];
    for (let i = 0; i < encoded.length; i++) {
      bytes.push(encoded.charCodeAt(i));
    }
    return bytes;
  }));
// with a static value
http("name").post("/")
  .body(ByteArrayBody(byteArrayOf(0, 1, 5, 4)))

// with a static value
http("name").post("/")
  .body(ByteArrayBody("#{bytes}"))

// with a function
http("name").post("/")
  .body(ByteArrayBody { session -> Base64.getDecoder().decode(session.getString("data")) }
  )
// with a static value
http("name").post("/")
  .body(ByteArrayBody(Array[Byte](0, 1, 5, 4)))

// with a static value
http("name").post("/")
  .body(ByteArrayBody("#{bytes}"))

// with a function
http("name").post("/")
  .body(ByteArrayBody(session =>
    Base64.getDecoder.decode(session("data").as[String]))
  )

InputStreamBody

InputStreamBody lets you pass a java.util.InputStream.

       
http("name").post("/")
  .body(InputStreamBody(session -> new ByteArrayInputStream(new byte[] { 0, 1, 5, 4 })));
Not supported by Gatling JS.
http("name").post("/")
  .body(InputStreamBody { session -> ByteArrayInputStream(byteArrayOf(0, 1, 5, 4)) })
http("name").post("/")
  .body(InputStreamBody(session => new ByteArrayInputStream(Array[Byte](0, 1, 5, 4))))

Forms

This section refers to payloads encoded with application/x-www-form-urlencoded or multipart/form-data, used with HTML forms.

formParam

formParam lets you pass non-file form input fields.

       
// with static values
http("name").post("/")
  .formParam("milestone", "1")
  .formParam("state", "open");

// with Gatling EL strings
http("name").post("/")
  .formParam("milestone", "#{milestoneValue}")
  .formParam("state", "#{stateValue}");

// with functions
http("name").post("/")
  .formParam("milestone", session -> session.getString("milestoneValue"))
  .formParam("state", session -> session.getString("stateValue"));
// with static values
http("name").post("/")
  .formParam("milestone", "1")
  .formParam("state", "open");

// with Gatling EL strings
http("name").post("/")
  .formParam("milestone", "#{milestoneValue}")
  .formParam("state", "#{stateValue}");

// with functions
http("name").post("/")
  .formParam("milestone", (session) => session.get("milestoneValue"))
  .formParam("state", (session) => session.get("stateValue"));
// with static values
http("name").post("/")
  .formParam("milestone", "1")
  .formParam("state", "open")

// with Gatling EL strings
http("name").post("/")
  .formParam("milestone", "#{milestoneValue}")
  .formParam("state", "#{stateValue}")

// with functions
http("name").post("/")
  .formParam("milestone") { session -> session.getString("milestoneValue") }
  .formParam("state") { session -> session.getString("stateValue") }
// with static values
http("name").post("/")
  .formParam("milestone", "1")
  .formParam("state", "open")

// with Gatling EL strings
http("name").post("/")
  .formParam("milestone", "#{milestoneValue}")
  .formParam("state", "#{stateValue}")

// with functions
http("name").post("/")
  .formParam("milestone", session => session("milestoneValue").as[String])
  .formParam("state", session => session("stateValue").as[String])

You can use multivaluedFormParam to set form parameters with multiple values:

       
http("name").post("/")
  // with static values
  .multivaluedFormParam("param", List.of("value1", "value2"));

http("name").post("/")
  // with a Gatling EL string pointing to a List
  .multivaluedFormParam("param", "#{values}");

http("name").post("/")
  // with a function
  .multivaluedFormParam("param", session -> List.of("value1", "value2"));
http("name").post("/")
  // with static values
  .multivaluedFormParam("param", ["value1", "value2"]);

http("name").post("/")
  // with a Gatling EL string pointing to a List
  .multivaluedFormParam("param", "#{values}");

http("name").post("/")
  // with a function
  .multivaluedFormParam("param", (session) => ["value1", "value2"]);
http("name").post("/") // with static values
  .multivaluedFormParam("param", Arrays.asList<Any>("value1", "value2"))

http("name").post("/") // with a Gatling EL string pointing to a List
  .multivaluedFormParam("param", "#{values}")

http("name").post("/") // with a function
  .multivaluedFormParam("param") { session -> listOf("value1", "value2") }
http("name").post("/")
  // with static values
  .multivaluedFormParam("param", Seq("value1", "value2"))

http("name").post("/")
  // with a Gatling EL string pointing to a Seq
  .multivaluedFormParam("param", "#{values}")

http("name").post("/")
  // with a function
  .multivaluedFormParam("param", session => Seq("value1", "value2"))

You can use formParamSeq and formParamMap to set multiple form parameters at once:

       
http("name").post("/")
  .formParamSeq(List.of(
      Map.entry("key1", "value1"),
      Map.entry("key2", "value2")
    )
  );

Map<String, Object> params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "value2");

http("name").post("/")
  .formParamMap(params);
// formParamSeq isn't implemented in Gatling JS, use formParamMap:

const params = {
  "key1": "value1",
  "key2": "value2"
};

http("name").post("/")
  .formParamMap(params);
http("name").post("/")
  .formParamSeq(listOf(
    AbstractMap.SimpleEntry<String, String>("key1", "value1"),
    AbstractMap.SimpleEntry<String, String>("key2", "value2")
  ))

http("name").post("/")
  .formParamMap(mapOf("key1" to "value1", "key2" to "value2"))
http("name").post("/")
  .formParamSeq(Seq(("key1", "value1"), ("key2", "value2")))

http("name").post("/")
  .formParamMap(Map("key1" -> "value1", "key2" -> "value2"))

form

You might want to repost all the inputs or a form previously captured with a form check.

Note you can override the form field values with the formParam and the likes.

       
http("name").post("/")
  .form("#{previouslyCapturedForm}")
  // override an input
  .formParam("fieldToOverride", "newValue");
http("name").post("/")
  .form("#{previouslyCapturedForm}")
  // override an input
  .formParam("fieldToOverride", "newValue");
http("name").post("/")
  .form("#{previouslyCapturedForm}") // override an input
  .formParam("fieldToOverride", "newValue")
http("name").post("/")
  .form("#{previouslyCapturedForm}")
  // override an input
  .formParam("fieldToOverride", "newValue")

formUpload

This method takes 2 parameters:

  • name the name of the form input can be a plain String, a Gatling Expression Language String, or a function.
  • filePath, the path to the file, can be a plain String, a Gatling Expression Language String, or a function.

See above how Gatling resolves filePath.

       
// with a static filepath value
http("name").post("/")
  .formParam("key", "value")
  .formUpload("file1", "file1.dat")
  // you can set multiple files
  .formUpload("file2", "file2.dat");

// with a Gatling EL string filepath
http("name").post("/")
  .formUpload("file1", "#{file1Path}");

// with a function filepath
http("name").post("/")
  .formUpload("file1", session -> session.getString("file1Path"));
// with a static filepath value
http("name").post("/")
  .formParam("key", "value")
  .formUpload("file1", "file1.dat")
  // you can set multiple files
  .formUpload("file2", "file2.dat");

// with a Gatling EL string filepath
http("name").post("/")
  .formUpload("file1", "#{file1Path}");

// with a function filepath
http("name").post("/")
  .formUpload("file1", (session) => session.get("file1Path"));
// with a static filepath value
http("name").post("/")
  .formParam("key", "value")
  .formUpload("file1", "file1.dat")
  // you can set multiple files
  .formUpload("file2", "file2.dat")

// with a Gatling EL string filepath
http("name").post("/")
  .formUpload("file1", "#{file1Path}")

// with a function filepath
http("name").post("/")
  .formUpload("file1") { session -> session.getString("file1Path") }
// with a static filepath value
http("name").post("/")
  .formParam("key", "value")
  .formUpload("file1", "file1.dat")
  // you can set multiple files
  .formUpload("file2", "file2.dat")

// with a Gatling EL string filepath
http("name").post("/")
  .formUpload("file1", "#{file1Path}")

// with a function filepath
http("name").post("/")
  .formUpload("file1", session => session("file1Path").as[String])

Multipart

bodyPart

You can set a multipart body as individual parts using bodyPart.

       
// set a single part
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
  );

// set a multiple parts
http("name").post("/")
  .bodyParts(
    StringBodyPart("partName1", "value"),
    StringBodyPart("partName2", "value")
  );
// set a single part
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
  );

// set a multiple parts
http("name").post("/")
  .bodyParts(
    StringBodyPart("partName1", "value"),
    StringBodyPart("partName2", "value")
  );
// set a single part
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
  )

// set a multiple parts
http("name").post("/")
  .bodyParts(
    StringBodyPart("partName1", "value"),
    StringBodyPart("partName2", "value")
  )
// set a single part
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
  )

// set a multiple parts
http("name").post("/")
  .bodyParts(
    StringBodyPart("partName1", "value"),
    StringBodyPart("partName2", "value")
  )

Once bootstrapped with one of the following methods, BodyPart has the following methods for setting additional options. Like in the rest of the DSL, almost every parameter can be a plain String, a Gatling Expression Language String, or a function.

       
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
      .contentType("contentType")
      .charset("utf-8")
      // part of the Content-Disposition header
      .fileName("fileName")
      // defaults to "form-data"
      .dispositionType("dispositionType")
      .contentId("contentId")
      .transferEncoding("transferEncoding")
      .header("name", "value")
  );
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
      .contentType("contentType")
      .charset("utf-8")
      // part of the Content-Disposition header
      .fileName("fileName")
      // defaults to "form-data"
      .dispositionType("dispositionType")
      .contentId("contentId")
      .transferEncoding("transferEncoding")
      .header("name", "value")
  );
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
      .contentType("contentType")
      .charset("utf-8")
      // part of the Content-Disposition header
      .fileName("fileName")
      // defaults to "form-data"
      .dispositionType("dispositionType")
      .contentId("contentId")
      .transferEncoding("transferEncoding")
      .header("name", "value")
  )
http("name").post("/")
  .bodyPart(
    StringBodyPart("partName", "value")
      .contentType("contentType")
      .charset("utf-8")
      // part of the Content-Disposition header
      .fileName("fileName")
      // defaults to "form-data"
      .dispositionType("dispositionType")
      .contentId("contentId")
      .transferEncoding("transferEncoding")
      .header("name", "value")
  )

StringBodyPart

Similar to StringBody.

RawFileBodyPart

where path is the location of a file that will be uploaded as is.

Similar to RawFileBody.

ElFileBodyPart

where path is the location of a file whose content will be parsed and resolved with the Gatling EL engine.

Similar to ElFileBody.

PebbleStringBodyPart

Similar to PebbleStringBody.

PebbleFileBodyPart

Similar to PebbleFileBody.

ByteArrayBodyPart

Similar to ByteArrayBody.

Pre-processing

processRequestBody

You might want to process the request body before it’s being sent to the wire. Gatling currently only provides one single pre-processor: gzipBody.

       
http("name").post("/")
  .body(RawFileBody("file"))
  .processRequestBody(gzipBody);
Not supported by Gatling JS.
http("name").post("/")
  .body(RawFileBody("file"))
  .processRequestBody(gzipBody)
http("name").post("/")
  .body(RawFileBody("file"))
  .processRequestBody(gzipBody)

Resources

Gatling provides a way to simulate a web browser fetching static.

A resources can be attached to a main request to define a list of HTTP requests to be executed once the main request completes.

Concurrency is defined by the HTTP version you’re using:

  • Over HTTP/1.1 (default), the number of concurrent requests per domain is capped by the maximum number of connections per domain, as defined by maxConnectionsPerHost. When the limit is reached, resources are fetched in the order they are passed to the resources block.
  • Over HTTP/2, the number of concurrent requests per domain is uncapped and all resources are always fetched concurrently.

The next step in the scenario will only be executed once all the resources have completed.

       
http("name").post("/")
  .resources(
    http("api.js").get("/assets/api.js"),
    http("ga.js").get("/ga.js")
  );
http("name").post("/")
  .resources(
    http("api.js").get("/assets/api.js"),
    http("ga.js").get("/ga.js")
  );
http("name").post("/")
  .resources(
    http("api.js")["/assets/api.js"],
    http("ga.js")["/ga.js"]
  )
http("name").get("/")
  .resources(
    http("api.js").get("/assets/api.js"),
    http("ga.js").get("/ga.js")
  )

Advanced options

requestTimeout

The default request timeout is controlled by the ``gatling.http.requestTimeout` configuration parameter.

However, you might want to use requestTimeout to override the global value for a specific request, typically a long file upload or download.

       
http("name").get("/")
  .requestTimeout(Duration.ofMinutes(3));
http("name").get("/")
  .requestTimeout({ amount: 3, unit: "minutes" });
http("name").get("/")
  .requestTimeout(Duration.ofMinutes(3))
http("name").get("/")
  .requestTimeout(3.minutes)

basicAuth and digestAuth

Just like you can define a global basicAuth or digestAuth on the HttpProtocol configuration, you can define one on individual requests.

proxy

Just like you can globally define a proxy on the HttpProtocol configuration, you can define one on individual requests.

disableFollowRedirect

Just like you can globally disable following redirect on the HttpProtocol configuration, you can define one on individual requests.

disableUrlEncoding

Just like you can globally disable URL encoding on the HttpProtocol configuration, you can define one on individual requests.

silent

See silencing protocol section for more details.

You can then make the request silent:

       
http("name").get("/")
  .silent();
http("name").get("/")
  .silent();
http("name").get("/")
  .silent()
http("name").get("/")
  .silent

You might also want to do the exact opposite, typically on a given resource while resources have been globally turned silent at the protocol level:

       
.resources(
  http("resource").get("/assets/images/img1.png")
    .notSilent()
);
.resources(
  http("resource").get("/assets/images/img1.png")
    .notSilent()
);
.resources(
  http("resource").get("/assets/images/img1.png")
    .notSilent()
)
.resources(
  http("resource").get("/assets/images/img1.png")
    .notSilent
)

sign

Just like you can define a global signing strategy on the HttpProtocol configuration, you can define one on individual requests.

transformResponse

Similarly, one might want to process the response before it’s passed to the checks pipeline:

transformResponse(transformer: (Response, Session) => Validation[Response])

The example below shows how to decode some Base64 encoded response body:

       
import io.gatling.http.response.*;

import java.nio.charset.StandardCharsets.UTF_8
import java.util.Base64

// ignore when response status code is not 200
.transformResponse((response, session) -> {
    if (response.status().code() == 200) {
      return new io.gatling.http.response.Response(
        response.request(),
        response.startTimestamp(),
        response.endTimestamp(),
        response.status(),
        response.headers(),
        new io.gatling.http.response.ByteArrayResponseBody(Base64.getDecoder().decode(response.body().string()), StandardCharsets.UTF_8),
        response.checksums(),
        response.isHttp2()
      );
    } else {
      return response;
    }
  }
);
Not supported by Gatling JS.
import io.gatling.http.response.*;

import java.nio.charset.StandardCharsets.UTF_8
import java.util.Base64

// ignore when response status code is not 200
.transformResponse { response, session ->
  if (response.status().code() == 200) {
    return@transformResponse Response(
      response.request(),
      response.startTimestamp(),
      response.endTimestamp(),
      response.status(),
      response.headers(),
      ByteArrayResponseBody(Base64.getDecoder().decode(response.body().string()), StandardCharsets.UTF_8),
      response.checksums(),
      response.isHttp2
    )
  } else {
    return@transformResponse response
  }
}
import java.nio.charset.StandardCharsets.UTF_8
import java.util.Base64

import io.gatling.http.response._

// ignore when response status code is not 200
.transformResponse {
  (response, session) =>
    if (response.status.code == 200) {
      response.copy(body = new ByteArrayResponseBody(Base64.getDecoder.decode(response.body.string), UTF_8))
    } else {
      response
    }
}

Edit this page on GitHub