CORS and static files¶
CORS¶
Two ways to enable it; both include automatic OPTIONS preflight routes.
Globally, from configuration:
server:
cors:
enabled: true
allowedOrigins: ["https://app.example"] # default ['*']
# allowedMethods: [GET, POST] # default: methods on the path
allowedHeaders: ["*"] # '*' echoes the preflight
exposedHeaders: []
allowCredentials: false
maxAge: 3600 # preflight cache, seconds
Per controller or route, with @CrossOrigin (same fields, camelCase):
@RestController('/info')
@CrossOrigin(origins: ['https://dashboard.example'])
class InfoController { ... }
Semantics:
- Route annotation replaces controller annotation replaces global config — whole-policy replacement, no field merging.
@CrossOriginenables CORS on its routes even when the global config is disabled.- Disallowed origins simply get no CORS headers (the browser blocks); a
valid preflight answers 204 with
Access-Control-Allow-*headers andVary: Origin. - With
allowCredentials: true, a*origin list echoes the caller's origin (the spec forbids literal*with credentials). - Registering your own
OPTIONSroute on a path suppresses the automatic preflight for it.
Static files¶
Serve a directory through the engine's hardened static handler (ETag, Range/conditional requests, path-traversal protection):
server:
static:
enabled: true
dir: public # filesystem directory
prefix: /static # URL prefix
index: index.html # served on directory hits
spa: false # true: serve index on ANY miss under the prefix
cacheMaxAge: 3600 # Cache-Control max-age, seconds
GET /static/…andHEADare served fromdir; anything outside the prefix is untouched, so API routes coexist.spa: trueturns misses under the prefix intoindex.html— client-side routers (Flutter web, React) work unhydrated.- Purely a runtime feature — no annotations, no codegen;
DianaServermounts it duringserve()when enabled.