Proxy
Portico answers a few things itself instead of passing them on: CORS, requests it can't route, and requests for services that aren't up. It can also hand the proxying to nginx, for parity with production.
At a Glance
- The
proxysection ofportico.yamlsets the port, address, base path, engine and CORS. - Portico listens on
0.0.0.0:4400by default;--portand--hostoverride it.
CORS
Your own frontend never needs CORS: it's served from the same origin as everything else. CORS only matters for callers on another origin, and Portico answers it for them:
- It echoes an allowed
Originback, with credentials allowed. - It answers preflight
OPTIONSrequests itself, allowing the requested method and headers. - It drops the
Access-Control-*headers your app sends for that origin, so the browser never sees two sets.
proxy.cors lists the allowed origins, and defaults to any origin (*). On a laptop, "any origin" includes any website you visit, so narrow it down:
proxy:
cors:
- http://localhost:3000
- https://*.cloudworkstations.devA leading *. in the host matches any subdomain. An empty list (cors: []) leaves CORS entirely to your app.
Error Responses
When Portico can't forward a request, it answers with JSON your frontend can show:
| Status | error | When |
|---|---|---|
404 | no_route | No route matches the path. |
503 | service_unavailable | The service is down, crashed or still starting. |
502 | upstream_error | The service accepted the connection, then failed. |
A 503 says what state the service is in, and for one that crashed, its exit code and last lines of output:
{
"error": "service_unavailable",
"service": "api",
"port": 3200,
"state": "exited",
"exit_code": 1,
"logs": ["Error: Cannot find module 'express'"]
}The Public URL
Behind a gateway, the URL in your browser isn't localhost:4400. When the first request arrives with an X-Forwarded-Host, Portico logs the URL it came in on, and portico status shows it from then on.
The nginx Engine
proxy.engine: nginx puts nginx in front instead of Portico's builtin proxy:
proxy:
engine: nginxPortico writes the nginx config from the same routes, to .portico/nginx/nginx.conf, and runs the nginx on your PATH. Without one, it runs nginx in a container (proxy.image and proxy.tag). With --watch, it rewrites the config and reloads nginx on changes.
Whatever nginx can't serve, a missing route or a service that's down, it passes to Portico, so error responses look the same on both engines. Only healthchecks differ: nginx sends requests to a container as soon as its port answers, without waiting for it to be healthy.
Next Steps
- Routing: paths, prefixes and forwarded headers.
- Configuration File Reference: every
proxykey.