Several services
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 SPECs 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:
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:
nameandspec(required),mount, and the settings of its document:proxy,stubs,scenarios,overrides,validation,security,operations,responses,generation,headers,asyncapi,graphqlandgrpc. These keys at the top of the file are every service’s defaults; a service’sstubs,scenarios,overridesandproxyreplace the defaults rather than adding to them.server,cors,simulation,tls,admin,log,contract,scripts,db,request_overridesandasyncapi.mqtt_portare 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 whoseHostheader names that host (any port), and may add aprefix.{port: N}is a listener of the service’s own (0picks a free one), which a.protofile’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 404no-service, which lists the mounts. Two services can’t share a name, nor can one’s mount hide another’s (/shopand/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-dirand--record-harname 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/+/openin both, orstatusand#): 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/). Anmqtt://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/serviceslists them with their mounts and URLs, the items of/routes(full paths),/scenarios,/overrides,/logand the status’sdocumentsname their service, and?service=NAMEnarrows 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 400admin-service-requiredotherwise; a service’s own endpoints (the gRPC ones,/contract/violations) answer 404 without it.PUT /simulation,POST /seedandPOST /reloadapply to every service unless one is named. - The contract report (
--report,GET /__apigenie/contract) has a section per service insections, each a whole report of its document with itsnameandmount, and asummarythat counts them together: requests, violations andcoverage.combined, the units of every service added up (OpenAPI branches, GraphQL fields, gRPC methods, AsyncAPI messages).--fail-onand--min-coverageapply 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.servicenames 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.
Was this helpful?