52

I have my site which is using nginx, and testing site with header testing tools e.g. http://www.webconfs.com/http-header-check.php but every time it says 400 bad request below is the out put from the tool. Though all my pages load perfectly fine in browser and when I see in chrome console it says status code 200OK.

HTTP/1.1 400 Bad Request => 
Server => nginx
Date => Fri, 07 Sep 2012 09:40:09 GMT
Content-Type => text/html
Content-Length => 166
Connection => close

I really don't understand what is the problem with my server config?

A bit of googling suggests to increase the buffer size using, and I increased it to following:

large_client_header_buffers 4 16k;

The same results persist.

Can some one guide me to the right direction?

ase
  • 13,231
  • 4
  • 34
  • 46
ʞɹᴉʞ ǝʌɐp
  • 5,350
  • 8
  • 39
  • 65
  • 89
    When nginx returns 400 (Bad Request) it will log the reason into error log, at "info" level. Hence an obvious way to find out what's going on is to configure [error_log](http://nginx.org/r/error_log) to log messages at "info" level and take a look into error log when testing. – Maxim Dounin Sep 08 '12 at 19:03
  • Sorry for the delayed response. Yeah thanks for the help Maxim. You are right logs helped me ultimately, I was changing the wrong ini files(was using reverse proxy so the setup was on multiple servers). My bad. I ll put a details explanation here. – ʞɹᴉʞ ǝʌɐp Sep 26 '12 at 14:18
  • Is the problem resolved? – lulalala Oct 26 '12 at 09:36
  • 4
    @deepak how did you fix the problem? TIA. – chr1x2 Mar 07 '13 at 08:37

9 Answers9

87

As stated by Maxim Dounin in the comments above:

When nginx returns 400 (Bad Request) it will log the reason into error log, at "info" level. Hence an obvious way to find out what's going on is to configure error_log to log messages at "info" level and take a look into error log when testing.

Community
  • 1
  • 1
ejoubaud
  • 5,013
  • 6
  • 37
  • 39
  • 7
    Just copy/pasting the answer from Maxim Dounin's comment here for readability. All credit should go to him so please up his comment if this answer helps. – ejoubaud Jun 25 '13 at 05:32
  • 8
    @NicolaeSurdu Make sure debug logging is turned on in nginx. You can do this by appending debug to the line that defines your error log in your sites conf file. So you'd have something like `server { error_log /path/to/error.log debug;` – skyjacks Nov 25 '14 at 10:56
  • 11
    @skyjacks i did what you've wrote, still empty log. – holms Apr 14 '15 at 23:09
  • 3
    have the same issue as holms and Nicolae – Krym Aug 05 '15 at 14:20
  • Something with SSL/TLS, regular HTTP works fine. Also maybe because ESET firewall, because it caches self-signed certificates in local CA, but disabled firewall for 10 minutes doesn't help. – happy_marmoset Apr 18 '16 at 06:32
  • For debug logging to work, nginx needs to be built with --with-debug, see “A debugging log”. http://nginx.org/en/docs/ngx_core_module.html#error_log – deweydb Apr 05 '17 at 17:26
  • Our NGINX is returning 400 to every healthcheck ping from the F5, the error log is at 'info' but nothing coming – Ed Randall Feb 02 '18 at 16:16
  • 5
    In my case, the request was being sent with invalid Host header value. – Nitb Jan 16 '19 at 13:58
  • @Holm, Sometimes it doesn't, for various reasons: In my case, while hosting multiple apps, I forgot to enable the app in question. Untill I ran `sudo ln -s /etc/nginx/sites-available/app_one /etc/nginx/sites-enabled` . All worked well. – Laenka-Oss Jul 19 '22 at 14:02
27

Yes changing the error_to debug level as Emmanuel Joubaud suggested worked out (edit /etc/nginx/sites-enabled/default ):

        error_log /var/log/nginx/error.log debug;

Then after restarting nginx I got in the error log with my Python application using uwsgi:

        2017/02/08 22:32:24 [debug] 1322#1322: *1 connect to unix:///run/uwsgi/app/socket, fd:20 #2
        2017/02/08 22:32:24 [debug] 1322#1322: *1 connected
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http upstream connect: 0
        2017/02/08 22:32:24 [debug] 1322#1322: *1 posix_memalign: 0000560E1F25A2A0:128 @16
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http upstream send request
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http upstream send request body
        2017/02/08 22:32:24 [debug] 1322#1322: *1 chain writer buf fl:0 s:454
        2017/02/08 22:32:24 [debug] 1322#1322: *1 chain writer in: 0000560E1F2A0928
        2017/02/08 22:32:24 [debug] 1322#1322: *1 writev: 454 of 454
        2017/02/08 22:32:24 [debug] 1322#1322: *1 chain writer out: 0000000000000000
        2017/02/08 22:32:24 [debug] 1322#1322: *1 event timer add: 20: 60000:1486593204249
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http finalize request: -4, "/?" a:1, c:2
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http request count:2 blk:0
        2017/02/08 22:32:24 [debug] 1322#1322: *1 post event 0000560E1F2E5DE0
        2017/02/08 22:32:24 [debug] 1322#1322: *1 post event 0000560E1F2E5E40
        2017/02/08 22:32:24 [debug] 1322#1322: *1 delete posted event 0000560E1F2E5DE0
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http run request: "/?"
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http upstream check client, write event:1, "/"
        2017/02/08 22:32:24 [debug] 1322#1322: *1 http upstream recv(): -1 (11: Resource temporarily unavailable)

Then I took a look to my uwsgi log and found out that:

        Invalid HTTP_HOST header: 'www.mysite.local'. You may need to add u'www.mysite.local' to ALLOWED_HOSTS.
        [pid: 10903|app: 0|req: 2/4] 192.168.221.2 () {38 vars in 450 bytes} [Wed Feb  8 22:32:24 2017] GET / => generated 54098 bytes in 55 msecs (HTTP/1.1 400) 4 headers in 135 bytes (1 switches on core 0)

And adding www.mysite.local to the settings.py ALLOWED_HOSTS fixed the issue :)

        ALLOWED_HOSTS = ['www.mysite.local']
PHZ.fi-Pharazon
  • 1,479
  • 14
  • 15
  • This helps although I'm not running uwsgi behind Nginx I'm running Tomcat, and checked in the Tomcat logs: `org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986` – Ed Randall Feb 02 '18 at 16:47
  • My problem was on a similar setup, setting `ALLOWED_HOSTS = ['.example.com']` (notice the leading dot) solved. – Alberto Chiusole Oct 03 '18 at 09:37
16

I had the same issue and tried everything. This 400 happened for an upstream proxy. Debug logged showed absolutely nothing.

The problem was in duplicate proxy_set_header Host $http_host directive, which I didn't notice initially. Removing duplicate one solved the issue immediately. I wish nginx was saying something other than 400 in this scenario, as nginx -t didn't complain at all.

P.S. this happened while migrating from older nginx 1.10 to the newer 1.19. Before it was tolerated apparently.

Yarik
  • 398
  • 4
  • 12
  • 2
    I can reconfirm that Nginx returns 400 if there are duplicate `Host` headers from upstream server(s). It logs the message on `info` level into error log though. This change was introduced in version 1.17.9 and conforms to RFC 7230: https://tools.ietf.org/html/rfc7230#section-5.4 – Alexander Azarov Nov 26 '20 at 09:14
  • Thanks for this answer. BTW I thought my error log was at info level, but I noticed a warn mode directive higher up in my nginx.conf It seems you can't override it deeper down the tree to be more verbose e.g. In server block – Phil Dec 17 '21 at 22:01
  • you saved my day, I have spent hours to check what's wrong with my config. Thank you – Duc Trung Mai Jul 21 '22 at 05:58
9

Just to clearify, in /etc/nginx/nginx.conf, you can put at the beginning of the file the line

error_log /var/log/nginx/error.log debug;

And then restart nginx:

sudo service nginx restart

That way you can detail what nginx is doing and why it is returning the status code 400.

John Difool
  • 5,572
  • 5
  • 45
  • 80
Camilo
  • 439
  • 5
  • 13
  • Apparently you can't enable the debug logging level unless nginx was compiled with the "--with-debug" option. Probably safer to use `info` level if you hit this scenario. – Phil Dec 17 '21 at 22:05
6

A cause can be invalid encoding in the URL request. Such as % being passed un-encoded.

Martlark
  • 14,208
  • 13
  • 83
  • 99
2

When nginx returns 400(bad request) it will log the reason into error log, at "info" level and take a look into error log when testing.

0

In my case, the issue was that port 443 wasn´t opened in the router

Lorenzo Lerate
  • 3,552
  • 3
  • 26
  • 25
0

If you get log just like this:

client xx.xx.xx.xx closed keepalive connection 

For this issue:"Connection: upgrade" causes 400 error that never reaches application code. Triggered by common nginx config. #17081

just set proxy_set_header Connection $http_connection

我零0七
  • 315
  • 3
  • 6
-1

normally, Maxim Donnie's method can find the reason. But I encountered one 400 bad request will not log to err_log. I found the reason with the help with tcpdump

Dan
  • 3,221
  • 7
  • 27
  • 24
  • what was the reason behind that 400? We have a simmilar situation and cant find the reason for those – Germán Lena Jun 13 '17 at 17:47
  • try tcpdump to find your reason. My issue it's that the request is blocked by the telecom operator when they read the http header. – Dan Aug 21 '17 at 10:24