Expose It over HTTP
The shop’s website has to list orders, show one, create one and approve one. A component serves no HTTP itself: it declares which of its operations appear as HTTP resources, and the gateway, a service of the runtime, serves them.
The orders are those of store.orders, the component Create a Component writes: create makes an order, approve approves a
pending one, and enumerate and observe are inherited.
§Declare the resources
Add an exposition section to the manifest:
# components/store.orders/manifest.toa.yaml
exposition:
/:
anonymous: true
io:output: true
GET: enumerate
POST: create
/:id:
GET: observe
PUT: approve The component’s routes are mounted under /<namespace>/<name>:
| Request | Calls |
|---|---|
GET /store/orders/ | store.orders.enumerate |
POST /store/orders/ | store.orders.create, with the body as input |
GET /store/orders/<id>/ | store.orders.observe of that order |
PUT /store/orders/<id>/ | store.orders.approve of that order |
:idis a route variable; its value selects the order.io:output: truelets replies through. Without it a request succeeds with204 No Contentand no body.anonymous: truelets anyone call these routes. Without an access rule a route answers401 Unauthorized.
Both are written once on / and apply to everything nested in it.
Opening the whole API to everyone is fine for a first run and for nothing else. Signing users in starts at Sign Users Up and In; the rules that say who may call what are in Restrict Who Can Call a Route.
§Run the application
The gateway is part of sys, one of the two processes npm start keeps under PM2, and it listens on port 8000. It
learns the routes from the components, so restart:
$ npm run restart The host the API is served on is named in the Context:
# context.toa.yaml
exposition:
authorities:
local: localhost:8000 §Send requests
Create an order:
$ curl -i http://localhost:8000/store/orders/
-H 'content-type: application/json'
-d '{"customer":"c1","items":[{"product":"kettle","quantity":1}],"total":4200}' HTTP/1.1 201 Created
content-type: application/json
{"id":"01a10df7b5e47692b3c64a94cff78bfd","VERSION":1,"DELETED":null,"REGION":0,"status":"pending","CREATED":1791235700196,"UPDATED":1791235700196,"customer":"c1","items":[{"product":"kettle","quantity":1}],"total":4200} Read it, this time as YAML. The gateway answers in the format the accept header asks for, and
reads bodies in the format content-type names:
$ curl -H 'accept: application/yaml' http://localhost:8000/store/orders/01a10df7b5e47692b3c64a94cff78bfd/ VERSION: 1
DELETED: null
REGION: 0
status: pending
CREATED: 1791235700196
UPDATED: 1791235700196
customer: c1
items:
- product: kettle
quantity: 1
total: 4200
id: 01a10df7b5e47692b3c64a94cff78bfd List the orders, then approve the one just created:
$ curl http://localhost:8000/store/orders/
$ curl -i -X PUT http://localhost:8000/store/orders/01a10df7b5e47692b3c64a94cff78bfd/ HTTP/1.1 200 OK
content-type: application/json
{"VERSION":2, … "status":"approved", … } §An error over HTTP
Approve the same order again. The error the operation returns is answered with 422 and its code
as the body:
$ curl -i -X PUT http://localhost:8000/store/orders/01a10df7b5e47692b3c64a94cff78bfd/ HTTP/1.1 422 Unprocessable Entity
content-type: application/json
{"code":"NOT_PENDING"} Other answers you will meet early:
| Status | When |
|---|---|
400 Bad Request | The body does not fit the operation’s input. The body of the response says why: "must have required property 'total'". |
401 Unauthorized | The route has no access rule that lets the caller in. |
404 Not Found | There is no such order, or no such route. A path without the trailing slash is answered "Trailing slash is required". |
405 Method Not Allowed | The route does not declare the method. |
§More
- Routes, variables and nesting: Lay Out the Routes.
- What a method may be mapped to: Map Methods to Operations.
- Filtering, sorting and paging a list: List with Filters, Sorting and Paging.
- Naming the properties a route takes and answers with: Choose What a Route Accepts and Returns.
- Statuses, formats and headers: What a Client Sends and Receives.
- The gateway as a process, its ports and its settings: Run and Configure the Gateway.