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 1state=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
header
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")
HttpHeaderNames.ContentType
.
You can find a list of the predefined constants here.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")
HttpProtocol
.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.
Body templates location are resolved the same way as for Feeder files.
Files must be placed in src/main/resources
or src/test/resources
when using a Maven (including the Gatling bundle), Gradle, or sbt project.
src/main/resources/data/foo.txt
data/foo.txt
.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 plainString
, a Gatling Expression LanguageString
, 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 plainString
, a Gatling Expression LanguageString
, 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 plainString
, a Gatling Expression LanguageString
, 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 %}" }"""))
Extensions
with registerPebbleExtensions(extensions: Extension*)
.
This can only be done once and must be done before loading any Pebble template.registerPebbleExtensions
function is not supported by Gatling JS.PebbleFileBody
.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 })));
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.
Unless you’ve explicitly set the Content-Type
header:
- if you’ve set at least one file part, Gatling will set it to
multipart/form-data
- otherwise, it will set it to
application/x-www-form-urlencoded
.
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 LanguageString
, or a function. - filePath, the path to the file, can be a plain
String
, a Gatling Expression LanguageString
, 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])
application/octet-stream
, and the character set defaults to the one configured in gatling.conf
(UTF-8
by default). Override them when needed.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);
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 theresources
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;
}
}
);
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
}
}