/ WhatILearned

Resolve Access-Control-Allow-Origin CORS error with Negroni

In one project, middleware Negroni is primarily being used to help with authentication of a Go webapp. Specifically, this project calls for building an API.

Whenever you're communicating with an API you'll encounter CORS (Cross Origin Resource Sharing) warnings/errors. These warnings tell you that the server you're communicating with has set up restrictions. Most of the times you need to explicitly allow or open up permissions so this is where having a middleware to allows you to plug in modules (as opposed to having to set it manually for every request that comes in).

You'll know it's a CORS error when you see an error in the Inspector that has the phrase:

'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

In setting up CORS for Negroni I saw that the recommended package for CORS was rs/CORS. They have a helpful example code on using rs/CORS with Negroni.

Some notes:

  • The default options are a good starting place but keep in mind that it allows access from any domain (due to the *) for AllowedOrigins and it only allows GET and POST
  • When Chrome first contacts an API it will send an opener using OPTIONS method. This means that you need to explicitly add OPTIONS to your AllowedMethods.
  • If you're passing any header information you'll need to make sure you're adding those headers (or set it to * in AllowedHeaders.
  • AllowedOrigins is not the URL that your API sits in, but the URL/domain that the API is being called from

In the end here's my config object.

apicors := cors.New(cors.Options{
    AllowedOrigins: []string{"https://thinClient.domain.com"},
    AllowedMethods: []string{"GET", "POST", "OPTIONS"},
    AllowedHeaders: []string{"X-Auth-Key", "X-Auth-Secret"},
    Debug: false}) //Setting debug to true helpfully puts information and almost every step in the console

By the way, here's an iron-ajax configured to send headers alongside the request and then load responseData variable with the result (as a json).

       headers='{"X-Auth-Key": "accessKey", "X-Auth-Secret":"accessSecret"}'