# How the mock picks a response

Source: https://apigenie.pl/docs/concepts/how-the-mock-picks-a-response

`apigenie-server openapi.yaml` answers every request from the document, without a line of code.
This page explains the decisions behind one answer, in the order the server takes them, so that
you can predict what a request gets and change it where you need to. The
[Responses](/docs/reference/server/responses) page of the reference states the same rules in
short.

The examples run against this document, saved as `pets.yaml` and served with
`apigenie-server pets.yaml`; `curl -i` shows the headers that say what was decided.

```yaml
openapi: 3.1.0
info: {title: Pets, version: 1.0.0}
servers:
  - url: https://api.example.com/v1
paths:
  /pets/{id}:
    get:
      operationId: getPet
      parameters:
        - {name: id, in: path, required: true, schema: {type: integer}}
      responses:
        "200":
          description: The pet
          content:
            application/json:
              schema: {$ref: "#/components/schemas/Pet"}
              examples:
                cat: {value: {id: 1, name: Tom, kind: cat}}
                dog: {value: {id: 2, name: Rex, kind: dog}}
        "404":
          description: No such pet
        default:
          description: An error
components:
  schemas:
    Pet:
      type: object
      required: [id, name]
      properties:
        id: {type: integer}
        name: {type: string}
        kind: {type: string, enum: [cat, dog]}
```

## 1. The route

The paths of the document are served under the path of its first server, `/v1` here, and as they
are: `GET /v1/pets/1` and `GET /pets/1` both reach `getPet`. `--base-path` replaces the prefix,
and `server.strict_base_path` in the configuration serves the paths only under it. When a literal
path and a templated one both match, the literal one wins: `/pets/mine` over `/pets/{id}`.

A path the document doesn't have is answered with 404, a method the path doesn't declare with 405
and an `Allow` header, both as [problem details](https://www.rfc-editor.org/rfc/rfc9457):

```text
$ curl -i -X DELETE http://127.0.0.1:4010/v1/pets/1
HTTP/1.1 405 Method Not Allowed
Content-Type: application/problem+json
Allow: GET
```

## 2. The request is checked

Before an answer is chosen, the request is checked against its operation: the parameters, the
body and the security requirements. A request that doesn't match gets 422 with the problems
instead of an answer, and one without the credentials a security requirement asks for gets 401:

```text
$ curl -i http://127.0.0.1:4010/v1/pets/abc
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://apigenie.pl/mock/errors#invalid-request",
  "title": "The request does not match the specification",
  "status": 422,
  "detail": "path.id: expected type integer, found string",
  ...
```

`validation.request: log` in the configuration reports such a request and answers it anyway. The
`__` query parameters of the next step are removed before the check, so `?__code=404` is not an
unknown parameter. [Validation and security](/docs/reference/server/validation) lists what is
checked.

## 3. Who answers

Several sources can answer a request. From the one that wins to the last resort:

1. **A script.** The `onRequest` hook of a [script](/docs/reference/server/scripts) that returns
   a response answers before the document's operations.
2. **The request itself.** The `Prefer` header, or the `__` query parameters, ask for a status, a
   named example, a generated body, a delay or a dropped connection: `Prefer: code=404`,
   `?__example=dog`.
3. **Scenarios and overrides.** The rules of the scenarios that are on (`--scenario`, the
   configuration, `x-apigenie-mock` in the document, the admin API) and the `operations` overrides
   of the configuration set the status, an example, a body or headers for the requests they
   match.
4. **Stubs.** With `--stubs DIR`, a recorded exchange whose method, path, query and body match
   answers (see [Record and replay](/docs/reference/server/contract-testing)).
5. **The document.** Its examples, else values generated from its schemas.

Each layer sets what it names and leaves the rest to the next. With this scenario on, `getPet`
answers 503:

```yaml
# apigenie-server.yaml
version: "1.0"
scenarios:
  outage:
    description: the backend is down
    rules:
      - match: {operationId: getPet}
        status: 503
        headers: {Retry-After: "30"}
```

```text
$ apigenie-server pets.yaml --scenario outage
$ curl -i http://127.0.0.1:4010/v1/pets/1
HTTP/1.1 503 Service Unavailable
Retry-After: 30
X-Apigenie-Mock-Operation: getPet
X-Apigenie-Mock-Source: scenario:outage
```

A request with `Prefer: code=200` still gets a 200 with the `cat` example, because the request's
own ask comes first; one with `?__example=dog` gets the 503, because the scenario set a status
that has no content, so there is no example to pick.

## 4. The status

When nothing above sets the status, the operation's responses decide: the lowest 2xx response,
else `2XX`, else the lowest declared status, else `default`. For `getPet` that is 200. An
operation with `204`, `202` and `400` answers 202; one with `2XX` alone answers 200; one with
`404` and `500` only answers 404.

A status the request asks for has to be declared, by its code, a range such as `4XX`, or
`default`: `Prefer: code=418` gets a 418 here, because `default` covers it, and a 500 from an
operation without `default`, whose detail says which statuses the operation has.

## 5. The body

The body is picked for the status, in this order:

- **The media type.** Content negotiation follows the request's `Accept`; a request that accepts
  only `text/plain` gets 406. Without an `Accept`, or with `*/*`, the response takes the media
  type of the request's body when it has one.
- **An example, else a generated value.** In the default static mode the media type's `example`,
  else its first named example (`cat` here), else the schema's `example` answer. What has none is
  generated from the schema, and `--dynamic` (or `responses.mode: dynamic`) generates every body.
  Generated values respect the types, the formats of the
  [format registry](/docs/reference/cli/formats), patterns, lengths, ranges, `enum`, `const`,
  `allOf`, `oneOf`, `readOnly` and `writeOnly`; `x-faker` on a property names the generator of
  its values ([Scenarios and extensions](/docs/reference/server/scenarios)).
- **XML.** A value for `application/xml`, `text/xml` or a `+xml` media type is written as XML,
  as the schema's `xml` objects describe it ([XML bodies](/docs/reference/server/validation#xml-bodies)).

```text
$ curl http://127.0.0.1:4010/v1/pets/1
{"id":1,"name":"Tom","kind":"cat"}
$ curl 'http://127.0.0.1:4010/v1/pets/1?__example=dog'
{"id":2,"name":"Rex","kind":"dog"}
$ curl -H 'Prefer: dynamic=true' http://127.0.0.1:4010/v1/pets/1
{"id":179,"name":"necessitatibus sint qui q"}
```

A status without content answers with an empty body, whatever example the request asks for.

## 6. The headers

The headers the response declares are filled in from their examples or schemas. Two headers of
the mock's own say what was decided, so that a surprising answer can be traced:

| Header | Says |
| --- | --- |
| `X-Apigenie-Mock-Operation` | The operation that answered: `getPet`. |
| `X-Apigenie-Mock-Source` | Where the answer came from: `example:cat`, `schema-example`, `generated`, `scenario:outage`, `stub:getPet-1`, `empty` for a status without content, `proxy` for a real server's answer. |

The log prints the same two facts on each line, and the [dashboard](/docs/reference/server/dashboard)
shows them per operation. `headers.diagnostics: false` in the configuration leaves the two
headers out.

## See also

- [Responses](/docs/reference/server/responses): the rules in short, the `Prefer` header and
  the network simulation.
- [Scenarios and extensions](/docs/reference/server/scenarios): the rules of a scenario,
  `x-apigenie-mock` and `x-faker`.
- [Validation and security](/docs/reference/server/validation): what step 2 checks, and XML
  bodies.
- [What the validating proxy checks](/docs/concepts/what-the-proxy-checks): the same server in
  front of a real one.
- [Mock and contract-test an API](/docs/guides/mock-and-contract-test-an-api): the guide.
