Skip to main content

HTTP DSL

Architecture

The HTTP DSL lets you use a specialised HTTP proxy (driver) to communicate with target servers, so that tests can be executed anywhere while the driver has access to the target resources.

The DSL provides handy methods to construct the final HTTP request as well as parse the output. There are specialised methods for REST calls with JSON parsing and specialised methods for SOAP calls with XML parsing. A separate set of methods supports authorization, including complex authentication flows.

Example:

class TestClass {

@Test
public void sampleTest(
@Capability(key = "browserName", value = "pn5-driver8")
HttpApplication client) {

client
.prepareRestRequest("https://example.com/api/animals", "GET")
.withBasicAuth("user", "password")
.withQueryParam("id", "1")
.sendAndGetResponse()
.assertStatus(200)
.assertPayloadContains("cat");
}

}

In the background, Pumpo#5 starts a session on the testing farm by instantiating an image of Driver8-Universal which then plays the role of a proxy.

Wrapping in custom objects

Instead of using the predefined methods in the HttpApplication interface, it is possible to define a custom interface that extends HttpApplication and to wrap the predefined actions into more business-oriented ones.

Example:

class TestClass {

@Test
public void sampleTest(MyCustomHttpApplication client) {

client
.checkThatAnimalIsInTheDirectory("1", "cat")
.checkThatAnimalIsInTheDirectory("2", "dog");

}

}

@Capability(key = "browserName", value = "pn5-driver8")
public interface MyCustomHttpApplication extends HttpApplication {

default MyCustomHttpApplication checkThatAnimalIsInTheDirectory(
String animalId,
String animalName) {

prepareRestRequest("https://example.com/api/animals", "GET")
.withBasicAuth("user", "password")
.withQueryParam("id", animalId)
.sendAndGetResponse()
.assertStatus(200)
.assertPayloadContains(animalName);

return null;
}
}

This pattern is common for all domains handled by Pumpo#5 and is the recommended coding style to keep tests readable, even for people without deep knowledge of implementation details.

Entry methods

HttpApplication::prepareHttpRequest

ParameterTypeDescription
urlStringThe target url to call
methodStringThe HTTP method to use

Creates a HttpRequestBuilder for the specified URL and method. The builder then allows you to set various parameters of the request before finally calling sendAndGetResponse().

The HttpRequestBuilder is a generic builder. Usually you will prefer the more specialised RestRequestBuilder or SoapRequestBuilder, obtained via the respective entry methods below.

HttpApplication::prepareRestRequest

ParameterTypeDescription
urlStringThe target url to call
methodStringThe HTTP method to use

Creates a RestRequestBuilder for the specified URL and method. This is a specialised builder for REST calls. In addition to all methods inherited from HttpRequestBuilder, it has additional ones that can work with JSON in both the request and the response.

HttpApplication::prepareSoapRequest

ParameterTypeDescription
urlStringThe target url to call

Creates a SoapRequestBuilder for the specified URL and method. This is a specialised builder for SOAP calls. In addition to all methods inherited from HttpRequestBuilder, it has additional ones that can work with XML.

Following specific functionality is implemented for SOAP:

  • The HTTP method is automatically set to POST.
  • If the header for Content-Type is not set manually, it will be set to text/xml; charset=utf-8 once the request is queued.

HTTP request methods

HttpRequestBuilder::withBasicAuth

ParameterTypeDescription
userStringUser name in plain
passwordStringPassword in plain

Instructs the driver to attach an HTTP Basic authentication header. The header will be constructed by the driver and will replace any authentication header if already present.

HttpRequestBuilder::withBearerAuth

ParameterTypeDescription
tokenStringToken to be used as bearer token

Instructs the driver to attach an HTTP Bearer authentication header. The header will be constructed by the driver and will replace any authentication header if already present.

HttpRequestBuilder::withBearerAuthResolved

ParameterTypeDescription
oAuthEndpointStringURL of the endpoint issuing access tokens
clientIdStringIdentification of the application
clientSecretStringSecret of the application in plain
scopeStringScope for the access token; please check the documentation of the target API to see what scope should be specified

Uses the driver to obtain an access token from an OAuth endpoint, then instructs the driver to attach an HTTP Bearer authentication header with the obtained token.

To authenticate to the OAuth endpoint, Basic authentication with the client id and client secret will be used.

In this version the token will represent the application only (client credentials grant flow). The client needs to have admin consent for the final resource upfront.

HttpRequestBuilder::withBearerAuthResolved

ParameterTypeDescription
oAuthEndpointStringURL of the endpoint issuing access tokens
clientIdStringIdentification of the application
clientSecretStringSecret of the application in plain
scopeStringScope for the access token; please check the documentation of the target API to see what scope should be specified
userNameStringUsername of the user to impersonate
userPasswordStringPassword of the user to impersonate in plain

Uses the driver to obtain an access token from an OAuth endpoint, then instructs the driver to attach an HTTP Bearer authentication header with the obtained token.

To authenticate to the OAuth endpoint, Basic authentication with the client id and client secret will be used.

In this version a user will be impersonated by specifying the user's credentials (resource owner password flow). This flow is not supported by all OAuth providers.

HttpRequestBuilder::withNtlmAuth

ParameterTypeDescription
domainStringThe domain of the user authenticated
usernameStringUsername
passwordStringPassword in plain
workstationStringWorkstation - In most cases this will not be verified by the server but should represent the hostname (without domain information) from which the authentication is done

Instructs the driver to proceed with the NTLM authentication flow when accessing the target API. The NTLM authentication flow will be realised on the driver side only.

NTLM authentication involves 3 request/response exchanges with the server. In case the authentication flow fails at some point, the last response will be returned to the client.

HttpRequestBuilder::withClientCertAuth

ParameterTypeDescription
certificateStringEither the path to a file containing an SSL certificate or a chain of certificates, or the file content itself
keyStringEither the path to a file containing a private key, or the file content itself

Instructs the driver to proceed with a client certificate authentication flow when accessing the target API. The client certificate authentication flow will be realised on the driver side only.

In case the authentication flow fails at some point the last response from the server will be returned to the client.

The private key can be either in PKCS1 or PKCS8 format.

HttpRequestBuilder::withHeader

ParameterTypeDescription
keyStringThe header key (e.g. Content-Type)
valueStringThe value of the header as plain (e.g. text/xml; charset=utf-8)

Instructs the driver to attach an HTTP header to the request. Currently, headers are implemented as a Map and do not allow specifying more than one value for a single key. This can be overcome by constructing the value as a comma-separated list of values. This is compliant with the relevant RFC and should be processed by the target server.

HttpRequestBuilder::withQueryParam

ParameterTypeDescription
keyStringThe parameter name
valueStringThe parameter value

Adds a query parameter to the requested URI. Takes care of the URL encoding. If a parameter is set multiple times, only the last value will be retained.

Does not check that the total URI length stays within the allowed size.

HttpRequestBuilder::withPayload

ParameterTypeDescription
payloadStringThe payload to be sent in plain text

If the payload is non-empty, it will be sent as the body of the HTTP request to the target server. If not set manually, the HTTP header Content-Length will be set to the size of the resulting body.

The payload should be text only; otherwise, either encode it or use the binary-safe method.

Works with any HTTP method — some combinations (e.g. sending a body with GET) don't make sense but will still be processed.

HttpRequestBuilder::withBinaryPayload

ParameterTypeDescription
payloadbyte[]The payload to be sent as plain bytes

If the payload is non-empty, it will be sent as the body of the HTTP request to the target server. If not set manually, the HTTP header Content-Length will be set to the size of the resulting body.

The content is immediately encoded in base64, which may affect results of methods such as replaceInPayload. The payload is decoded back to a byte array on the driver side. The driver will not set headers such as Content-Disposition automatically.

Works with any HTTP method — some combinations (e.g. sending a body with GET) don't make sense but will still be processed.

HttpRequestBuilder::withPayloadFromFile

ParameterTypeDescription
pathStringPath of the text file to be loaded

The payload will be loaded from a file (as plain text). To load the file, the getResource() method of the classloader attached to the HttpApplication is used. Typically, the path should be specified relative to resource folders.

The file should be text only; otherwise, either encode it or use the binary-safe method.

HttpRequestBuilder::withBinaryPayloadFromFile

ParameterTypeDescription
pathStringPath of the binary file to be loaded

The payload will be loaded from a file (as plain bytes). To load the file, the getResource() method of the classloader attached to the HttpApplication is used. Typically, the path should be specified relative to resource folders.

The content is immediately encoded in base64, which may affect results of methods such as replaceInPayload. The payload is decoded back to a byte array on the driver side. The driver will not set headers such as Content-Disposition automatically.

HttpRequestBuilder::withMultipartFile

ParameterTypeDescription
nameStringThe form field name of the part
databyte[]The raw bytes of the file content
filenameStringThe filename to report for this part

Adds a file part to a multipart/form-data request body. The Content-Type of the part defaults to application/octet-stream.

The request body is built by the driver as multipart/form-data with a boundary generated automatically. The Content-Type header of the overall request is set to multipart/form-data; boundary=... unless it was already set explicitly via withHeader.

Cannot be combined with withPayload, withBinaryPayload, withPayloadFromFile or withBinaryPayloadFromFile on the same request - a request is either a single body or a multipart one. Mixing them throws an IllegalStateException.

HttpRequestBuilder::withMultipartFile

ParameterTypeDescription
nameStringThe form field name of the part
databyte[]The raw bytes of the file content
filenameStringThe filename to report for this part
contentTypeStringThe Content-Type to report for this part, e.g. "image/png"

Same as the overload above but lets you specify the Content-Type of the part explicitly instead of defaulting to application/octet-stream.

HttpRequestBuilder::withMultipartText

ParameterTypeDescription
nameStringThe form field name of the part
valueStringThe text value of the part

Adds a plain text field part to a multipart/form-data request body.

Cannot be combined with withPayload, withBinaryPayload, withPayloadFromFile or withBinaryPayloadFromFile on the same request - a request is either a single body or a multipart one. Mixing them throws an IllegalStateException.

Any number of withMultipartFile and withMultipartText calls can be combined on the same request; each is sent as a separate part, in the order they were added.

Example:

client
.prepareRestRequest("https://example.com/api/upload", "POST")
.withMultipartText("description", "invoice scan")
.withMultipartFile("file", fileBytes, "invoice.pdf", "application/pdf")
.sendAndGetResponse()
.assertStatus(200);

HttpRequestBuilder::replaceInUrl

ParameterTypeDescription
placeholderStringToken searched in the URL
valueStringValue that will replace the token

Replaces given token in the URL by the provided value. The String::replace method will be used so no regular expressions are allowed here and all occurrences will be replaced.

HttpRequestBuilder::replaceInPayload

ParameterTypeDescription
placeholderStringToken searched in the payload
valueStringValue that will replace the token

Replaces given token in the payload by the provided value. The String::replace method will be used so no regular expressions are allowed here and all occurrences will be replaced.

In case a binary payload was attached, the replace method will be run over the base64 encoding of the payload.

HttpRequestBuilder::sendAndGetResponse

Completes the builder pattern and sends the request to the driver. Parses the received response as HttpResponse where the fluent interface continues.

REST request methods

RestRequestBuilder inherits all methods from HttpRequestBuilder plus implements the following ones:

RestRequestBuilder::withJsonFromPojoPayload

ParameterTypeDescription
payloadObjectObject to be serialised as JSON

Serialises the provided object to JSON using a Jackson ObjectMapper with no additional settings. The provided object's class may have JSON mappings specified by Jackson annotations. The resulting JSON is then attached as the payload (body) of the HTTP request.

RestRequestBuilder::sendAndGetResponse

Completes the builder pattern and sends the request to the driver. Parses the received response as RestResponse where the fluent interface continues.

SOAP request methods

SoapRequestBuilder inherits all methods from HttpRequestBuilder plus implements the following ones:

SoapRequestBuilder::withAction

ParameterTypeDescription
soapActionObjectAction to be set in the header

Adds or replaces the header with key SOAPAction with the provided value.

SoapRequestBuilder::withXmlFromPojoPayload

ParameterTypeDescription
payloadObjectObject to be serialised as XML

Serialises the provided object to XML using a JAXB marshaller and puts it in the body of a SOAP envelope. The resulting XML is then attached as the payload (body) of the HTTP request. The JAXB marshaller correctly processes namespaces, which must be specified using XmlElement annotations at every level. SOAP servers are usually permissive and do not require namespaces to be set correctly at every level.

SoapRequestBuilder::sendAndGetResponse

Completes the builder pattern and sends the request to the driver. Parses the received response as SoapResponse where the fluent interface continues.

HTTP Response members

Some methods of HttpResponse allow continuing the fluent interface, while others return specific objects that need to be processed separately. There are also public attributes accessible for manual processing and code simplification.

List of public attributes:

AttributeTypeDescription
initialRequestInitialHttpRequestInitial request with additional public attributes (url, method, headers, payload)
statusintStatus code of the response
headersMap<String,String>Map of headers where header names are keys
payloadStringBody of the response, may be null

HttpResponse::assertStatus

ParameterTypeDescription
statusintExpected status code

Asserts that the received response has the provided status code.

HttpResponse::assertBodyIsNotEmpty

Asserts that the received response has a non-empty body.

HttpResponse::assertPayloadContains

ParameterTypeDescription
needleStringSearched text in the payload

Asserts that the received response payload (body) contains at least one occurrence of the provided string. No regular expressions are allowed in this case.

HttpResponse::assertHeaderReceived

ParameterTypeDescription
headerNameStringName of the header to search

Asserts that the received response headers contain at least one with the provided name.

HttpResponse::assertHeaderContains

ParameterTypeDescription
headerNameStringKey of the header to search
valueStringValue to search in the header

Asserts that the received response has a header with the provided name and that the header content contains the provided value. No regular expressions are allowed here.

HttpResponse::printRequest

Prints the initial request to stdout for debugging purposes.

HttpResponse::printResponse

Prints the response to stdout for debugging purposes.

HttpResponse::andThen

Returns to the initial state where entry methods can be used for the next request without breaking the fluent interface.

REST Response members

RestResponse inherits all members of HttpResponse and adds a few more methods for working with the response payload as JSON.

RestResponse::payloadAs

ParameterTypeDescription
poJoClassClassClass to use when mapping the JSON to an object

Returns an object of type PoJoClass deserialised using a Jackson ObjectMapper.

RestResponse::assertThatPayload

ParameterTypeDescription
poJoClassClassClass to use when mapping the JSON to an object

Returns an object of type ObjectAssert<PoJoClass> from the AssertJ library that allows running various assertions on the object after deserialising to PoJoClass using Jackson.

RestResponse::payloadBinaryAsByteArray

Returns the payload as plain bytes decoded from Base64.

This method should be used only when the response payload is detected to be binary (e.g. image, document, etc.) and therefore was encoded to Base64 using a heuristic approach.

SOAP Response members

SoapResponse inherits all members of HttpResponse and adds a few more methods for working with the response payload as XML.

SoapResponse::payloadAs

ParameterTypeDescription
poJoClassClassClass to use when mapping the XML to an object

Returns an object of type PoJoClass deserialised using a Jackson XmlMapper.

SoapResponse::payloadXmlAs

ParameterTypeDescription
poJoClassClassClass to use when mapping the XML to an object

Returns an object of type PoJoClass deserialised using a JAXB unmarshaller. Unlike the previous method, where JsonProperty annotations can be used to map XML elements to PoJo attributes and XML namespaces are ignored, JAXB requires XmlElement annotations with a namespace matching the one used inside the XML at every level. This requires more work but can be more accurate in some cases.

SoapResponse::assertThatPayload

ParameterTypeDescription
poJoClassClassClass to use when mapping the XML to an object

Returns an object of type ObjectAssert<PoJoClass> from the AssertJ library that allows running various assertions on the object after deserialising to PoJoClass using Jackson XmlMapper.