# Migrate from Prism

Source: https://apigenie.pl/docs/guides/migrate-from-prism

This guide moves a repository that mocks its API with `prism mock` and checks it with
`prism proxy` to `apigenie-server`: the addresses, the `Prefer` header, request validation, the
validation proxy, the CI step, and what has no counterpart. It starts from Prism 5.x and an
OpenAPI file, `openapi.yaml`.

You need the CLI installed; the [Quickstart](/docs/quickstart) shows how. Keep Prism installed
until the last step, so you can send the same requests to both.

## What changes and what stays

| | Prism | API Genie |
| --- | --- | --- |
| Mock | `prism mock openapi.yaml` | `apigenie-server openapi.yaml` |
| Validation proxy | `prism proxy openapi.yaml http://localhost:8080` | `apigenie-server openapi.yaml --proxy-to http://localhost:8080` |
| Address | `http://127.0.0.1:4010`, CORS on | the same; `--host`, `--port`, `--cors off` |
| Documents | OpenAPI 2.0 and 3.x, Postman collections | OpenAPI 3.0 to 3.2, Swagger 2.0, AsyncAPI 3, `.proto`, GraphQL |
| Picking an answer | `Prefer: code=404`, `example=cat`, `dynamic=true`; `__code`, `__example`, `__dynamic` | the same, plus `delay=`, `drop=` and `scenario=` |
| Static and dynamic | examples by default, `-d` generates | the same; `--dynamic` or `-d`, `--seed N` in both |
| An invalid request | 422 with problem details | the same, with 400, 401, 415 for what they name |
| An invalid answer of the mock | logged; a 500 with `--errors` | logged and counted in `X-Apigenie-Mock-Violations`; a 500 with `--strict` |
| Violations of the proxy | `sl-violations` header; errors with `--errors` | `X-Apigenie-Mock-Violations` headers; errors with `--strict`; a report, and exit status 5 |
| Reload on change | always | `--watch` |
| Configuration | the command line | the command line, or `apigenie-server.yaml` ([Configuration](/docs/reference/server/configuration)) |
| Docker | `stoplight/prism:5` | `mykulyak/apigenie-server` |
| npm | `@stoplight/prism-cli` | `@mykulyak/api-genie` |

## Run both on the same document

```sh
prism mock openapi.yaml
apigenie-server openapi.yaml
```

```text
Listening on http://127.0.0.1:4010/v1 (spec: openapi.yaml, 12 operations)
Admin API: http://127.0.0.1:4010/__apigenie
Dashboard: http://127.0.0.1:4010/__apigenie/ui
```

Both listen on `127.0.0.1:4010` with CORS headers on, so a client keeps its base URL. Prism
ignores the document's `servers` and serves `/pets`; `apigenie-server` serves the paths under the
path of the first server, `/v1/pets`, and as they are, `/pets`, so both addresses answer. The
dashboard shows every request, what answered it and what was wrong with it, which Prism prints to
the terminal; `--log-level debug` and `--log-bodies` print it too.

```sh
curl http://127.0.0.1:4010/pets
```

Both answer with the first example of the lowest 2xx response. Where a response has no example,
Prism's static mode fills the schema with `"string"` and `0`; `apigenie-server` generates a value
that fits the schema, its formats, patterns, ranges and enums, in static mode too
([Responses](/docs/reference/server/responses)). Prism's `--ignoreExamples` has `--dynamic` as
its closest counterpart.

## Pick the answer of a request

The `Prefer` header and the `__` query parameters keep their names:

```sh
curl http://127.0.0.1:4010/pets -H 'Prefer: code=404'
curl http://127.0.0.1:4010/pets -H 'Prefer: example=empty'
curl 'http://127.0.0.1:4010/pets?__dynamic=true'
```

`apigenie-server` adds `delay=1500` (answer after 1.5 seconds), `drop=reset` (reset the
connection; `close`, `timeout` and `truncate` too) and `scenario=outage`
([choosing a response per request](/docs/reference/server/responses#choosing-a-response-per-request)).
For an answer that should hold for a while, such as an outage of one backend, a
[scenario](/docs/reference/server/scenarios) in the document or in the configuration is switched
on with `--scenario` or in the dashboard, instead of a `Prefer` header on every request.
Prism's `__server` query parameter has no counterpart: the mock does not check which server a
request is meant for.

## Request validation and security

Both answer a request that does not match its operation with 422 and problem details. Prism
answers with the operation's own 422 or 400 response when it declares one; `apigenie-server`
answers with the problems it found: 422 for a parameter or a body that does not match its schema,
400 for a body it cannot parse, 415 for a media type the operation does not declare
([Validation and security](/docs/reference/server/validation)).

Both answer 401 when a request carries no credentials for the operation's security requirements.
Prism stops there; `apigenie-server` can check the credentials themselves:

```yaml
# apigenie-server.yaml
version: "1.0"
security:
  mode: enforce
  credentials: {api_keys: {apiKey: [secret]}, bearer_tokens: [token]}
```

Prism's `--errors` on the mock, which turns an invalid answer of the mock into a 500, is
`--strict`. Without it, the problems of an answer are logged and counted in the
`X-Apigenie-Mock-Violations` header of that answer.

## Dynamic data and x-faker

`-d` and `--seed` keep their names. `x-faker` on a property carries over, with one change: the
providers are named like those of today's faker.js, `person.firstName` and `internet.email`, not
`name.firstName` of the Faker 6 that Prism uses; the [Faker](/docs/reference/cli/faker) page
lists them with their arguments:

```yaml
Pet:
  type: object
  properties:
    name: {type: string, x-faker: person.firstName}
    owner: {type: string, x-faker: internet.email}
```

A property can get its provider from the configuration instead, without touching the document
(`User.email: {faker: internet.email}` under `generation`), and string properties called like
`email`, `first_name` or `city` get fitting values without any of this. Prism's
`--json-schema-faker-fillProperties`, which adds properties the schema does not declare, has no
counterpart.

## The validation proxy

```sh
prism proxy openapi.yaml http://localhost:8080
apigenie-server openapi.yaml --proxy-to http://localhost:8080
```

Every request goes to the real server, and the request and the server's answer are checked
against the document. The violations of an exchange come back in headers, `sl-violations` in
Prism, `X-Apigenie-Mock-Violations` and `X-Apigenie-Mock-Violations-Detail` here, and in the
dashboard's Contract screen with the coverage of the document
([Contract testing](/docs/reference/server/contract-testing)).

- `--errors` is `--strict`: a request that does not match the document is answered with 422
  without reaching the server, and a server answer that does not match is replaced by a 502.
- `--validate-request false` is `validation: {request: off}` in the configuration.
- Prism mocks an operation the server answers with 501. `--proxy-mode fallback` does the same,
  and also when the server answers 404, does not answer in time or cannot be reached.
- Both add `Deprecation: true` to the answers of a deprecated operation.
- `--upstream-proxy` has no counterpart: the server reaches the upstream directly.

## The report in CI

With Prism, CI learns about a contract violation from a test that fails behind `--errors`.
`apigenie-server` writes a report when it stops, and exits with status 5 when the contract failed:

```sh
apigenie-server openapi.yaml --proxy-to http://localhost:8080 \
  --report contract.json --report-junit contract.xml --fail-on errors --min-coverage 80 &
API_URL=http://localhost:4010 npm test
curl -X POST http://localhost:4010/__apigenie/shutdown
wait $!
```

`--fail-on errors` fails the job on an error-level violation even when every test passed, and
`--min-coverage 80` when the tests leave more than a fifth of the document untested. The JUnit
report has one test case per operation, so the CI system shows it next to the test results.
[Mock and contract-test an API](/docs/guides/mock-and-contract-test-an-api) has the whole flow,
with `--record` and `--replay` for tests that run without the real services.

## Several APIs

Prism runs one document per process, on a port each:

```sh
prism mock -p 5000 pets.yaml
prism mock -p 5001 orders.yaml
```

One `apigenie-server` serves them as [services](/docs/reference/server/services), each at its own
mount, with a proxy or a scenario of its own:

```sh
apigenie-server pets.yaml orders.yaml
```

```text
Listening on http://127.0.0.1:4010 (2 services)
  pets    http://127.0.0.1:4010/pets/v1 (spec: pets.yaml, 12 operations)
  orders  http://127.0.0.1:4010/orders (spec: orders.yaml, 5 operations)
```

## What has no counterpart

- **Callbacks.** Prism sends the callback requests an operation declares; `apigenie-server` does
  not mock callbacks, webhooks or links.
- **Postman collections as the document.** The mock serves OpenAPI, Swagger 2.0, AsyncAPI,
  Protobuf and GraphQL documents. `apigenie test import` turns a Postman collection into `.http`
  files for [apigenie test](/docs/reference/cli/test).
- **`-m`, the second process for the log.** The server is one native process.
- **`__server`, `--upstream-proxy` and `--json-schema-faker-fillProperties`**, as noted above.

## Remove Prism

When the same requests get the answers you expect from both: replace `prism mock` and
`prism proxy` in the scripts, the Compose file and the CI pipeline, remove `@stoplight/prism-cli`
from the development dependencies, and swap the Docker image:

```sh
docker run --rm -p 4010:4010 -v "$PWD:/mnt/data" mykulyak/apigenie-server openapi.yaml
```

The image listens on every interface of the container, as `prism mock -h 0.0.0.0` did.
