# Several services

Source: https://apigenie.pl/docs/reference/server/services
Part of the reference of [apigenie-server](https://apigenie.pl/docs/reference/server.md).
Its other pages: [Responses](https://apigenie.pl/docs/reference/server/responses.md), [Scenarios and extensions](https://apigenie.pl/docs/reference/server/scenarios.md), [Scripts](https://apigenie.pl/docs/reference/server/scripts.md), [Document store](https://apigenie.pl/docs/reference/server/store.md), [Validation and security](https://apigenie.pl/docs/reference/server/validation.md), [Contract testing (validating proxy)](https://apigenie.pl/docs/reference/server/contract-testing.md), [Session recording and replay](https://apigenie.pl/docs/reference/server/recording.md), [AsyncAPI](https://apigenie.pl/docs/reference/server/asyncapi.md), [Protobuf / gRPC](https://apigenie.pl/docs/reference/server/grpc.md), [GraphQL](https://apigenie.pl/docs/reference/server/graphql.md), [Configuration](https://apigenie.pl/docs/reference/server/configuration.md), [Dashboard and admin API](https://apigenie.pl/docs/reference/server/dashboard.md), [TLS](https://apigenie.pl/docs/reference/server/tls.md).

One `apigenie-server` serves several documents at once: an application's backends, a gateway's
services, the HTTP and the messaging side of a system. Each document is a **service** with a name
and a **mount**, where its clients reach it. Several `SPEC`s on the command line are services named
after their files (`pets.openapi.yaml` is `pets`) and mounted at `/<name>`; a `.proto` file gets a
port of its own. A single `SPEC` is served as before, without a prefix. The configuration's
`services` list says more:

```yaml
version: "1.0"
server: {port: 4010}
validation: {request: enforce}   # the services' defaults
services:
  - name: pets
    spec: pets.yaml               # mounted at /pets
  - name: orders
    spec: orders.yaml
    mount: /shop/orders
    proxy: {target: "http://localhost:8080", mode: fallback, record_har: session.har}
    scenarios:
      outage: {rules: [{status: 503}]}
  - name: events
    spec: events.asyncapi.yaml
    mount: {host: events.localhost}
  - name: greeter
    spec: greeter.proto
    mount: {port: 50051}
```

- **What a service sets**: `name` and `spec` (required), `mount`, and the settings of its document:
  `proxy`, `stubs`, `scenarios`, `overrides`, `validation`, `security`, `operations`, `responses`,
  `generation`, `headers`, `asyncapi`, `graphql` and `grpc`. These keys at the top of the file are
  every service's defaults; a service's `stubs`, `scenarios`, `overrides` and `proxy` replace the
  defaults rather than adding to them. `server`, `cors`, `simulation`, `tls`, `admin`, `log`,
  `contract`, `scripts`, `db`, `request_overrides` and `asyncapi.mqtt_port` are the server's.
- **Mounts.** A path prefix (`/shop/orders`, default `/<name>`) on the server's port: the service
  gets the requests below it, without the prefix, so its own base path and routes are unchanged.
  `{host: events.localhost}` takes the requests whose `Host` header names that host (any port), and
  may add a `prefix`. `{port: N}` is a listener of the service's own (`0` picks a free one), which a
  `.proto` file's service needs: gRPC clients can't add a prefix. Requests the server's port gets
  go to the services by host first, then to the one with the longest prefix (prefixes end at a `/`);
  the others get 404 `no-service`, which lists the mounts. Two services can't share a name, nor
  can one's mount hide another's (`/shop` and `/shop/orders`), nor can a mount cover the admin API.
- **Proxies** forward the path without the mount's prefix, after their own (`--proxy-to`'s path).
  `--proxy-to`, `--stubs`, `--record-dir` and `--record-har` name one document's upstream and
  recordings, so with several services they are refused: set them per service.
- **WebSocket**: an AsyncAPI service's channels and a GraphQL service's subscriptions share the
  server's port, below the service's mount (`ws://127.0.0.1:4010/events/v1/rooms/1`).
- **MQTT**: one broker for every service (`--mqtt-port`). Topics are served as the documents name
  them, unless the MQTT channels of two services can match the same topic (`doors/+/open` in both,
  or `status` and `#`): then the topics of each of those services start with its name
  (`front/doors/7/open`). The startup line shows the prefix (`MQTT topics under front/`). An
  `mqtt://` upstream goes with one document.
- **The log** names the service of each event (`"service": "orders"` in JSON, `[orders]` in the
  stylish log); event paths are within the service, without its prefix. Ids are unique across the
  services.
- **The admin API** (`/__apigenie`) covers every service: `GET /__apigenie/services` lists them with
  their mounts and URLs, the items of `/routes` (full paths), `/scenarios`, `/overrides`, `/log` and
  the status's `documents` name their service, and `?service=NAME` narrows any endpoint to one
  service. An endpoint of one service's resources (a scenario of two services, `PUT /overrides`,
  `/state`, `/db`, `/spec`) needs it when more than one service could be meant, and answers 400
  `admin-service-required` otherwise; a service's own endpoints (the gRPC ones,
  `/contract/violations`) answer 404 without it. `PUT /simulation`,
  `POST /seed` and `POST /reload` apply to every service unless one is named.
- **The contract report** (`--report`, `GET /__apigenie/contract`) has a section per service in
  `sections`, each a whole report of its document with its `name` and `mount`, and a `summary` that
  counts them together: requests, violations and `coverage.combined`, the units of every service
  added up (OpenAPI branches, GraphQL fields, gRPC methods, AsyncAPI messages). `--fail-on` and
  `--min-coverage` apply to that summary: a violation of any service fails the run, and the
  combined coverage must reach the threshold (the reason names the service with the lowest). The
  JUnit report has a suite per service.
- **The HAR file** of the proxies is one per server: every service that records names the same
  file, and each entry's `_apigenie.service` names its service; URLs keep the mount's prefix.
- **Reloads** (`--watch`): a service reloads when its document, stubs or scripts change; a change
  of the configuration reloads every service. Adding or removing a service needs a restart.
