Skip to main content
Version: v3

CORS Requests

Building a public API requires to allow Cross-Origin Request Sharing.

Enable Cross-Origin Resource Sharing (CORS)

If you are building a web application, you may not need to enable CORS for your API. See here the section Origins that Do not Match.

If you want different origins to make requests to your API from a browser, you need to enable Cross-Origin Resource Sharing.

You can do that by adding a route handler and a special hook to your API root controller (APIController in this example).

import { Context, Hook, HttpResponseNoContent, Options } from '@foal/core';

@Hook(() => response => {
// Every response of this controller and its sub-controllers will be added this header.
response.setHeader('Access-Control-Allow-Origin', '*');
})
export class ApiController {

subControllers = [
// your sub-controllers
];

@Options('*')
options(ctx: Context) {
const response = new HttpResponseNoContent();
response.setHeader('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
// You may need to allow other headers depending on what you need.
response.setHeader('Access-Control-Allow-Headers', 'Content-Type');
return response;
}

// Some other routes (ex: @Get('/users'), etc)

}

CORS Requests and Authorization header

If your API requires a token to be sent in the Authorization header, then the name of this header should be specified in the options handler.

  @Options('*')
options(ctx: Context) {
const response = new HttpResponseNoContent();
response.setHeader('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
response.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');
return response;
}

The same goes with other headers: X-Requested-With, etc.

CORS Requests and Cookies

If your API uses cookies (for authentication for example), then you should specify it in the hook with the Access-Control-Allow-Credentials header.

@Hook(ctx => response => {
response.setHeader('Access-Control-Allow-Origin', ctx.request.get('Origin') || '*');
response.setHeader('Access-Control-Allow-Credentials', 'true');
})

In the browser, your HTTP client must also have its withCredentials option set to true.

Examples

XMLHttpRequest

const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

Axios

axios.get('http://example.com/', { withCredentials: true });

Angular HttpClient

this.http.get('http://example.com/', { withCredentials: true });

fetch

fetch('http://example.com/', { credentials: 'include' });