For those unfamiliar with CORS, it’s a way of precisely defining who and how a remote origin may invoke an API’s resources. Generally, due to the same-origin policy, a web browser will only allow the invocation of resources that reside on the same origin as the requesting page. This mitigates a range of malicious script attacks by preventing interaction with remote resources.

However, if we want our resource to be callable by some (or all) other origins, then we need to define a CORS policy which let’s user agent know what’s allowed.

Preparation

If you have the apiman quickstart running [1], you next need to deploy the echo-service to act as the backend API for our demo. Substitute the path below for the appropriate one corresponding to the version you downloaded.

Let’s give it a go

For the purposes of this blogpost we’ll contrive a scenario that allows us to demonstrate a variety of the plugin’s functionality. However, if your precise use-case isn’t covered here, you should still investigate the settings page, as a raft of configuration options are available that will likely achieve what you need.

Create an Organization called Foo, then create an API called Bar. Set your API’s Implementation URL to be http://127.0.0.1:8080/apiman-echo, and select Rest as the type. Move to the Plans tab and tick Make this API public.

Plugin settings

Let’s configure the settings as follows:

Option

Value(s)

Explanation

Terminate on CORS error

true

We’ll not hit the backend if there’s a CORS validation error. In some instances, a non-preflighted CORS request would otherwise cause a real invocation of the API whose results would be ignored by the user agent.

How long the browser should cache your CORS policy for (to avoid repeated preflight requests).

After saving you’ll see it’s description says something along the lines of:

Cross-origin requests from 1 origin(s) will be permitted upon satisfying method, header and credential constraints. Denied requests will be terminated. Preflight requests will be cached for 9001 delta seconds.

Access Control to Major Tom

Generally, it’s the job of the user agent to set the Origin header, such as a browser or mobile client. However, we’ll be using cURL to simulate a variety of scenarios so we can test things out without actually needing to set up a load of different domains.

Notice that we were given the thumbs down without the API ever being hit; for most use cases this is a good thing, as it avoids unnecessary load on a API where the user agent is going to throw away the response anyway.

Not got the head(er) for it

Even if our origin is correct, we need to pass other checks, such as headers. In this preflighted example, we’ll try to make a request with a header that we’ve not allowed: X-SECRET.

You can see that the Response-Counter header is in our list of headers that can be exposed. If we were building a Javascript XHR then the browser would allow you to see the Response-Counter but not other non-standard fields such as X-Powered-By.

Preflight checks

Let’s do something a bit more complex that requires a preflight request, which is essentially a pre-check to see whether our request is acceptable before attempting it for real. We’ll set the headers Access-Control-Request-Method to PATCH and Access-Control-Request-Headers to X-APIMAN-EXCELLENT. Again, we’re using a permitted origin.