# Send REST requests

> Payloads from files, the redirects the REST pack follows and the ones it leaves to the scenario, cookies, and the headers custom steps give a request.

Source: https://axx.nimbusxr.us/next/guides/send-rest-requests/

A scenario registers a REST service, adds requests to it, executes them and checks their responses ([rest pack](https://axx.nimbusxr.us/next/references/packs/rest/)). This page is about what happens in between: the payload a request sends, the redirects it follows, the cookies it sends, and the headers a custom step gives it. To sign a request as a webhook is signed, or authorize it with a token, see [Test webhooks and tokens](https://axx.nimbusxr.us/next/guides/webhooks-and-tokens/).

The REST pack tests APIs. To test a web app's pages, forms or sign-in, use the web-core pack: a real browser keeps cookies, follows redirects and submits forms, as the app's users do ([Test web apps](https://axx.nimbusxr.us/next/guides/test-web-apps/)).

## Payloads from files

A payload starts from an example of the service's OpenAPI specification, from an empty template the payload property steps fill, or from a file of the project, sent as it is:

```gherkin
Scenario Outline: A shop's order system registers the parcels it exports
  Given a POST request to /api/parcels
  And a request payload using an application/json requests/<order>.json resource
  When the request is executed
  Then the response status code is 201
  And the response header Location is '/api/parcels/<reference>'

  Examples:
    | order      | reference   |
    | order-7731 | PX-REG-1301 |
    | order-7732 | PX-REG-1302 |
```

- **The file is found like the other files steps name:** relative to the `resources` directories, or to `axx.yaml`'s directory.
- **A JSON payload can still change.** The payload property steps edit it, like a payload from an example. A property inside an object the payload lacks creates the object: `recipient.name` and `recipient.postcode` fill an empty template's `recipient` ([ADR 0010](https://github.com/nimbusxr/axx/blob/main/docs/adr/0010-payload-properties-create-missing-objects.md)).
- **A form payload file is a JSON object.** With `application/x-www-form-urlencoded`, its properties are sent form-encoded.
- **No OpenAPI specification is needed,** which suits a callback or a webhook that the service has no contract for.

A [fixture factory](https://axx.nimbusxr.us/next/guides/fixture-factories/) keeps such files in one place and checks them against a schema. The parcels example generates the two files above with `requests/registrations.factory.yaml`, from the `ParcelRequest` schema of the service's OpenAPI contract.

## Several requests in one scenario

Requests are numbered in the order a scenario adds them. The first is the default, which steps without an ordinal use; every other request is added, executed and checked with its ordinal:

```gherkin
Scenario: A registered parcel can be looked up by its reference
  Given a POST request to /api/parcels
  And a request payload using an application/json content example
  And the request payload property reference is 'PX-REG-1401'
  And a 2nd ordered GET request to /api/parcels/PX-REG-1401
  When the request is executed
  And the 2nd ordered request is executed
  Then the response status code is 201
  And the 2nd ordered response status code is 200
  And the response payload property reference is 'PX-REG-1401' for 2nd ordered response
```

- **Add a request before using it:** a step that uses the 2nd request fails unless a 2nd was added before it. `axx validate` says so, with the step that adds it.
- **A second `a GET request to …` adds the 1st again**, and fails: write it as `a 2nd ordered GET request to …`. `axx validate` shows the line to write.
- **A check names its response:** `the 2nd ordered response status code is 200`, or `… for 2nd ordered response` at the end of the other response steps. A check without one reads the 1st response.

## Find an item in a list

A property can pick items out of a list with a JSONPath filter: `parcels[?(@.reference=='PX-REG-1401')].status` is the status of that parcel. The value a check compares is the list of what matched, so one match reads `'["delivered"]'`.

```gherkin
Then the response payload property parcels[?(@.reference=='PX-REG-1401')].status is '["delivered"]'
And the response payload property parcels[?(@.service=~/Next\sday\sair/)].reference is '["PX-REG-1401"]'
```

- **A path is one word**, without spaces. To match a text with spaces, use `=~` and a regular expression, where `\s` stands for the space.
- **`=~` matches the whole text**, as Jayway's JSONPath does: `/Next\sday/` doesn't match "Next day air", while `/Next\sday.*/` does.

## Redirects

| Request | Redirects it follows | The response the steps check |
|---|---|---|
| `GET`, `HEAD` | 301, 302, 303, 307 and 308 | the one the redirects lead to |
| `POST`, `PUT`, `PATCH`, `DELETE`, ... | `303 See Other`, with a `GET` | after a 303, the one it leads to |
| `POST`, `PUT`, `PATCH`, `DELETE`, ... | none of the others: 301, 302, 307 and 308 | the redirect itself |

A redirect the pack follows is not kept: its status, its `Location` header and the cookies it sets are not the response's, and the response steps cannot check them. The scenario's log shows the request as the step sent it and the status at the end, like `GET http://localhost:8080/api/parcels/PX-REG-1010 -> 200 OK (12ms, 412 bytes)`.

The `GET` that follows a 303 has no body and no `Content-Type`. It has the request's other headers, `Authorization` and `Cookie` only when the redirect stays on the same host or goes to a subdomain of it.

### Redirects left to the scenario

A `POST`, `PUT`, `PATCH` or `DELETE` answered with 301, 302, 307 or 308 has the redirect as its response. Check its status and its `Location` header, and send the request it leads to as the next ordered request. Say a service moved its API from `/api/v1` and answers the old paths with `308 Permanent Redirect`:

```gherkin
Scenario: A cancellation sent to the old API cancels the parcel through its redirect
  Given a 1st ordered DELETE request to /api/v1/parcels/PX-REG-1010
  And a 2nd ordered DELETE request to /api/parcels/PX-REG-1010
  When the 1st ordered request is executed
  And the 2nd ordered request is executed
  Then the 1st ordered response status code is 308
  And the response header Location is '/api/parcels/PX-REG-1010' for 1st ordered response
  And the 2nd ordered response status code is 204
```

The scenario sends both requests, then checks both responses: the redirect, where it leads, and the cancellation there.

## Cookies

The REST pack keeps no cookies. A `Set-Cookie` response header is never sent back: not with the scenario's later requests, and not to where a redirect leads. A request carries the cookies its scenario gives it, in its `Cookie` header (`the request header Cookie is '...'`), and nothing else, so scenarios running side by side never share cookies.

## Headers from custom steps

A custom step changes a request the pack's steps built, before it is executed, through the request's headers: `Header()` returns the headers it is sent with, and `Set`, `Add` and `Del` change them. `SetHeader(name, value)` does what the request header steps do. [Write custom steps](https://axx.nimbusxr.us/next/guides/write-custom-steps/#change-a-rest-request) has an example.
