I am developing a REST API with Fantom and afBedSheet. I need to allow cross-origin resource sharing so that I can call my RESTful services via AJAX from the UI which runs on a different web container on a different port.
I am currently doing this in request handler methods:
res.headers["Access-Control-Allow-Origin"] = "http://localhost:8080"
But as the API grows and the number of request handlers grow, it is no longer practical. I'm wondering how can I inject that header in every response. I have Googled the question but only found a reference to a document from a very old version of afBedSheet which doesn't seem relevant anymore. Can anyone provide an example, please?
CORS has to be set up manually but as mentioned, it's not that difficult. Anything that becomes repetitive in request handler methods can usually be squirrelled away somewhere, and setting HTTP response headers is no different. These can be set via BedSheet Middleware:
using afIoc
using afBedSheet
const class CorsMiddleware : Middleware {
@Inject private const HttpRequest req
@Inject private const HttpResponse res
@Inject private const ResponseProcessors processors
new make(|This|in) { in(this) }
override Void service(MiddlewarePipeline pipeline) {
// echo back in the response, whatever was sent in the request
res.headers["Access-Control-Allow-Origin"] = req.headers["Origin"]
res.headers["Access-Control-Allow-Methods"] = req.headers["Access-Control-Request-Method"]
res.headers["Access-Control-Allow-Headers"] = req.headers["Access-Control-Request-Headers"]
// deal with any pre-flight requests
if (req.httpMethod == "OPTIONS")
processors.processResponse(Text.fromPlain("OK"))
else
pipeline.service
}
}
Note that the above will enable CORS on all requests - handy for dev, but for live code you should be more choosy and validate any given Origins, Methods, and Headers.
BedSheet Middleware
should be contributed to the MiddlewarePipeline
service:
@Contribute { serviceType=MiddlewarePipeline# }
static Void contributeMiddleware(Configuration config) {
config.set("myApp.cors", config.autobuild(CorsMiddleware#)).before("afBedSheet.routes")
}
Note that CorsMiddleware
is inserted into the pipeline before BedSheet routes to ensure it gets executed.