Custom Headers on Every Response With golangs httprouter
While developing a web service in go with httprouter I ran into an issue when I used the Fetch API on a POST request:
Fetch API cannot load http://192.168.99.100:3030/token-auth. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
Because my web client is running on localhost and my API is running in Docker container from 192.168.99.100 a CORS violation occurred. To resolve this issue (at least in development) I need to set the following header in the server’s response.
Access-Control-Allow-Origin: *
Initially, I handled this with middleware and decorated every handler.
Setting Access-Control-Allow-Origin to all isn’t recommend for production unless you’re creating a public API. Using a middleware on every handler can get ugly, but it let me focus on the front-end. In my next phase of development, I added an Authorization Bearer token on protected requests and got the same error again.
This time, the error was the result of the Fetch API making an OPTIONS preflight request. httprouter automatically handles OPTIONS requests; I could override those OPTIONS handlers for every protected POST, or I could find a way to set custom headers for every response.
With the above solution, I can intercept the incoming requests, update the response headers then pass the request to httprouter. Now, all requests get the same headers including httprouters automatic handlers. On the next run of the application, I came back with another CORS error.
Fetch API cannot load http://192.168.99.100:3030/p. Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.
In the OPTIONS preflight request, there is an “Access-Control-Allow-Headers” header with a value of “authorization”. Per CORS rules, the response must have the “Access-Control-Allow-Headers” header set with one or more matching values to the request. I updated the intercept to include the appropriate header.
With some configuration, this method of wrapping the server can be effectual for fine tuning response headers on all requests without adding to growing middleware chain and allowing you to take advantage of httprouters automatic handlers. Since this method makes use of golangs standard HTTP lib, you should be able to use any compatible router in the Server struct.