Recently, I've been working on an API server built with Node.js and hosted on AWS Elastic Beanstalk.
The server manages resources for organisations. Apart from the Authorisation token, which tells us who the user is, we added another token which identifies the organisational resources he wants to access. A user can be part of multiple organisations, so we decided to follow this approach.
The header was named ORG_API_KEY. The staging environment was Heroku; everything worked perfectly until deployed to the AWS Elastic Beanstalk production server. We kept getting 401 error (missing api_key).
After hours of debugging, I found out that Elastic Beanstalk running Nginx as a reverse proxy by default has the Nginx option underscores_in_headers
turned off (That is the default for Nginx). Somehow Heroku and other servers I've worked with have this option turned on, so I never noticed.
It was now a matter of preference to either turn on this option using our .ebextensions
config or modify our headers and change the underscores to dash. Just to be sure, I tried both approaches, which worked.
curl --HEADER "ORG_API_KEY: some-random-token" # won't work
curl --HEADER "ORG-API-KEY: some-random-token" # works fine
To enable this option using Nginx config, you'll have to navigate to the following folder or create one if it does not exit .ebextensions > nginx > conf.d
in this folder you should have a configuration file or create one (myconfig.conf or any other name with .conf extension). I already have a config file which I use to increase the size of a request so I added a new line. My config now looks like this;
client_max_body_size 20M;
underscores_in_headers on;
Using underscore is valid according to HTTP standards, in their defence, they (Nginx) said:
This is done in order to prevent ambiguities when mapping headers to CGI variables as both dashes and underscores are mapped to underscores during that process.
The reason is valid, so instead of turning on the option of allowing underscores, we modified the headers changing underscores to dash. I didn't like the bug, but I enjoyed the learning. What other server configurations have you learnt about?
Top comments (2)
FYI: Werkzeug, the Python library, has the following condition when constructing header objects:
This means that if you serve your code with Werkzeug or anything else that is using it (like Flask for example), it will skip over all headers that have the underscore in its name.
I find the argumentation a bit weak: "don't use underscores in your headers" because… some server implementation strips them by default. Should we also not use large payloads because they are rejected by default in nginx?