CORS, cookies and base path
These options of createApp() adapt the API to where it runs: browsers on other origins, cookies, a reverse proxy.
CORS
Browsers block the requests of a page to an API on another origin, unless the API allows them (Cross-Origin Resource Sharing). CORS is disabled by default: enable it with the origins you trust.
- Preflight requests from an allowed origin get a
204listing the methods of the routes of the path, before any middleware: authentication does not block them. - Every response to an allowed origin gets the CORS headers, errors included, so that the client can read a
401or a422. - Other origins get responses without CORS headers: the browser blocks them. CORS is not an access control: the server still answers, and authentication protects the routes.
Vary: Originis added to every response, unlessoriginis'*', so that caches do not mix origins.- An
originfunction that throws is logged, and refuses the origin. - The CORS headers are added before the
onResponsehooks, which see the final response. - Native routes of the HTTP server (registered in
beforeRoutes, for instance) are not covered: configure CORS on the server for them.
List the origins you trust explicitly. A function that accepts any origin, combined with credentials: true, lets any website make requests with the cookies of your users.
With @dotpress/auth in cookie mode, the origins allowed with credentials are also trusted by its protection against cross-site request forgery (see Cookie mode and CSRF).
Behind API Gateway or a Lambda Function URL, configure CORS either in AWS or in Dotpress, not both: AWS answers preflight requests before the function runs.
Cookies
Request cookies are parsed on every request, without a dependency:
Set them with ctx.res.setCookie(name, value, options) and remove them with clearCookie(). The options are those of the Set-Cookie header: maxAge, expires, path (/ by default), domain, secure, httpOnly, sameSite, partitioned, priority.
No security option is applied for you: set httpOnly, secure and sameSite for every cookie holding a session or a secret. See Responses.
Base path
To serve the API under a sub-path, for instance https://example.com/my-app/api/users behind a reverse proxy shared by several apps, use one of these options, depending on what the proxy forwards:
basePathprefixes every route, plugin routes included:GET /usersis served at/my-app/api/users, and other paths get a404.ctx.req.pathandapp.routeshold the full paths.publicBasePathdoes not change the routing. It changes the paths seen by the browser: the paths of the cookies set by plugins, the URLs of the API reference, and the paths built withpublicPath().
The two options cannot be combined. ctx.publicPath(), app.publicPath() and api.publicPath() (in plugins) give the browser path of a route path. Redirects are not prefixed automatically, since they may target a page outside of the API:
Client IP address behind a proxy
ctx.req.ip is the address of the client as seen by the HTTP server. Behind a load balancer or a reverse proxy, it is the address of the proxy, unless the server trusts the proxy headers (X-Forwarded-For): configure it on the server, for instance the trust proxy setting of Express, or the trustProxy option of Fastify. Only trust the proxies you run: a client can send any X-Forwarded-For header.
The login throttling of @dotpress/auth uses this address: see Passwords and brute force.