Django sending 400 "Bad request"
Mar 7, 2016 17:27 · 320 words · 2 minute read
Missing ALLOWED_HOSTS
In settings.py
ALLOWED_HOSTS = ("example.com",)
where example.com is actually the domain you are running the app on. That did the trick. The thing is that in production mode (DEBUG=False), Django doesn’t serve all domains.
Recently, while deploying a Django application with gunicorn and nginx I encountered the following problem: application returns Bad Request 400 for all requests. The solution was simple - just add this to your settings.py file.
A list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent an attacker from poisoning caches and triggering a password reset emails with links to malicious hosts by submitting requests with a fake HTTP Host header, which is possible even under seemingly-safe web server configurations. ALLOWED_HOSTS Django docs - official documentation for further information. This will work with both Nginx and Apache.
Nginx doesn’t pass $host to your application
Make sure the nginx config is configured to pass the Host variable via proxy. This is done via adding the following to the location directives:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $server_name;
Full example of the configuration may look like follows:
server {
listen 80;
server_name example.com;
access_log off;
location /static/ {
alias /opt/projectname/static/;
}
location / {
proxy_set_header Host $host;
proxy_pass http://localhost:8000;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
}
}
Host name has underscores
Sometimes, Django sending 400 Bad request because of domain name. Despite the fact that domain name can actually contain the underscores, the host names can not. Thus, Django won’t validate it even though you have ALLOWED_HOSTS settled correctly. Here is the regular expression that Django actually uses to validate the host name:
host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9:]+\])(:\d+)?$")