HTTP requests¶
A scenario builds one request at a time. method sends it and clears the path, query, body, form, and multipart parts. The URL, headers, cookies, and auth stay for the next request.
Try it¶
Start the mock from the quick start, then save this as http.feature:
Feature: HTTP greeting
Scenario: read a greeting
* url baseUrl
* path 'hello'
* param language = 'en'
* header Accept = 'application/json'
* method get
* status 200
* match response.message == 'Hello, Ada!'
The request is GET /hello?language=en. The mock returns status 200 and a JSON message; both assertions pass. Open http.html to inspect the URL, headers, and response.
Response values¶
After method:
response,responseStatus,responseHeaders,responseBytes,responseCookies, andresponseTimeare set.responseTimeis milliseconds and includes reading the body.- JSON and XML are parsed from the content type. Any other body stays text.
responseHeadersvalues are lists.match header Namereads the first value.- Cookies stay in a scenario jar: host, domain, path, expiry, and Secure, including across redirects.
- A body over 8 MiB fails the step.
- A path segment is escaped once.
path 'a b'requests/a%20b.
Request¶
| Step | Effect |
|---|---|
url expression |
Base URL. A relative path is joined to it. |
path a, b |
Appends segments. Each segment is evaluated. |
param name = expression |
One query parameter. |
params expression |
An object of query parameters. |
header name = expression |
Sets one header. |
headers expression |
An object of headers. |
cookie name = expression |
Adds a cookie. An object with a value field uses that field. |
cookies expression |
An object of cookies. |
form field name = expression |
One form field. |
form fields expression |
An object of form fields. |
request expression |
Body. A string is sent as text, a native XML document as XML, and other data as JSON. |
method name |
Sends the request. get, post, put, patch, delete, head, options. |
status code |
Fails unless responseStatus equals the code. |
GET and HEAD put form fields on the query string and drop multipart parts. POST, PUT, and PATCH use the body in this order: multipart parts, then an explicit request, then application/x-www-form-urlencoded form fields.
Null query, header, and form values are skipped. Lists produce repeated values. A null configured header removes that name from the request overlay.
Multipart¶
* multipart field message = 'hello'
* multipart file note = { read: 'note.txt', filename: 'note.txt', contentType: 'text/plain' }
* method post
multipart fields takes an object. multipart files takes a list of { name, read, filename, contentType } or an object whose keys are the part names. A string part is text/plain. An object or list part is JSON. The filename defaults to the base name of read. The content type defaults from the file extension, or application/octet-stream.
The multipart Content-Type, including the boundary, is set on the request. A configure headers function can still replace it.
Auth¶
configure auth sets credentials for the scenario. Choose one of these forms; each replaces the previous auth setting. An explicit Authorization header takes precedence.
* configure auth = { type: 'basic', username: 'ada', password: 'secret' }
* configure auth = { type: 'bearer', token: token }
* configure auth = { type: 'oauth2', accessTokenUrl: '/token', clientId: 'id', clientSecret: 'secret', scope: 'read' }
OAuth2 is the client-credentials grant. The first request of the scenario posts grant_type, client_id, client_secret, and scope to accessTokenUrl. A relative token URL is resolved from the request's scheme and host. The access token is cached for the rest of the scenario, including retries and called features. A non-2xx token response fails the step.
Retry¶
retry until applies to the next method only. count is the maximum total number of attempts. interval is the pause between attempts, in milliseconds. Each attempt uses the request timeout. Header hooks and request hooks run on every attempt.
Headers from config¶
configure headers accepts an object or a function. The function runs before every request and its object is merged onto the request. For the same header name, the configured value replaces the scenario value. Auth runs first, so the configured headers can replace Authorization too.
method also accepts an expression that returns the method name. configure readTimeout aliases timeout; values must be positive integer milliseconds within Go's duration range. configure strictResponseParsing = true fails on malformed JSON or XML for the corresponding response content type.
TLS, proxy and SOAP¶
For a private CA, configure its PEM file:
Add cert and key for mutual TLS. algorithm accepts TLS, TLSv1.2 or TLSv1.3. configure ssl = true disables certificate verification for test servers; use a CA when you want verification. Java keystores are not supported.
| Setting | Effect |
|---|---|
configure connectTimeout = 5000 |
TCP connection timeout in milliseconds. |
configure proxy = 'http://localhost:8080' |
Send requests through a proxy. |
configure proxy = null |
Disable the proxy. |
soap action 'urn:operation' |
Set SOAPAction, use text/xml and send POST. |
A proxy object accepts uri, username, password and nonProxyHosts (Go glob patterns). TLS, proxy and connection settings require a standard Go HTTP transport when using a custom Go client.
CA trust pools
A supplied CA is added to the transport's existing trust pool, or to the system pool if the transport has none.
GraphQL¶
Send the query and variables as a JSON request. Check GraphQL's errors field as well as HTTP status: a server may return query errors with status 200.
Feature: GraphQL users
Scenario: find a user
* url baseUrl
* path 'graphql'
* def query = 'query User($id: ID!) { user(id: $id) { id name } }'
* request { query: '#(query)', variables: { id: '42' } }
* method post
* status 200
* match response.errors == '#notpresent'
* match response.data.user == { id: '42', name: '#string' }
Save as graphql.feature and run gi test graphql.feature --var baseUrl=https://your-api.example. Replace that URL with a server exposing /graphql and the user query above. GraphQL uses the same HTTP and match steps as REST.
Common mistakes¶
| Symptom | Check |
|---|---|
| The next request loses its path or body | Set them again before each method; these builders are cleared after sending. |
| A header comparison sees a list | responseHeaders contains lists. Use match header Content-Type contains 'application/json' to check the first value. |
| A malformed JSON response remains text | Enable configure strictResponseParsing = true to fail parsing instead. |
| Polling stops too soon | retry.count is the total attempts, including the first. retry until applies only to the next method. |
| A GraphQL request returns 200 but has query errors | Check response.errors in addition to HTTP status. |
| Authentication does not use the configured token | An existing Authorization header takes precedence over configured auth; a configured header callback can also replace it. |