nginx 1.21.1 - spaces in request line - 400 Bad Request - nginx

Since version 1.21.1 nginx now returns a HTTP/1.1 400 Bad Request error when there is a space in the request url.
From the nginx official changelog:
*) Change: now nginx always returns an error if spaces or control
characters are used in the request line.
My server is still receiving some requests with spaces in the GET query string from some older Android devices. I know that spaces in the url need to be encoded, but I have a few special cases where this is not possible right now.
Is there any option to turn off this new behaviour without having to revert to version 1.21.0?

Related

Tomcat not handling encoded URL

I'm hitting a problem with Tomcat 8.5 when using URL that needs to be encoded. The URL contains [ and ] characters, and those are correctly being encoded as %5B and %5D. I send the request with curl e.g. curl http://somewhere.com/foo%5Bbar%5D but Tomcat throws a 400 error stating that "The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).".
In the Tomcat access log the URL is report in its decoded form along with the 400 response.
I do have an nginx reverse proxy in between, but I don't think that would be decoding the URL.
Any ideas what's wrong?
So it turned out to be a know problem with the nginx ingress in that when it has to rewrite the URL is decodes it and sends the decoded URL downstream to Tomcat which then blows up.
There's various discussions on this, but as I needed to fix this as part of the K8S ingress definition I used the info described here. I've not sure where the upstream_balancer thing comes from but must be some black magic, but it does seem to fix the problem. I'm sure there are other approaches that would also work.

jetty BadMessage: 400 No Host for HttpChannelOverHttp

I have seen previous posts about Jetty BadMessage: 400 No Host for HttpChannelOverHttp and I can confirm that I am able to repeat the problem.
I have a Jetty route in Camel Blueprint, which creates another request and forwards on to a Dropwizard service via Camel HTTP.
.process(new Processor() {
//Creates Object for request
}
.marshal(jsonFormat)
.convertBodyTo(String.class)
.setHeader(Exchange.HTTP_URI, simple(serviceEndpoint))
.setHeader(Exchange.HTTP_METHOD, constant(HttpMethod.POST))
.to(userviceEndpoint)
When this request executes, I see the following error on Dropwizard
WARN [2014-11-12 23:15:35,333] org.eclipse.jetty.http.HttpParser: BadMessage: 400 No Host for HttpChannelOverHttp#3aa99dd2{r=0,a=IDLE,uri=-}
This happens constantly, and this problem does not occur when I send a request to the DW service using SOAP-UI (using the serviceEndpoint URL).
Please if anyone has solved this problem, I would like to know how. Thank you.
Capture your network traffic, and post the HTTP request headers you are sending to Jetty.
Odds are that your HTTP client is not sending the Host: header (which is required on HTTP/1.1)
In my case, I was setting header with null value. After removing header having null value from request solved the issue.
Jetty Version: 9.3.8
I got this error when I was making a request with incorrectly formatted headers. So instead of having the header as "X_S_ID: ABC" I had "X_S_ID: ["X_S_ID":BLAH]". So the error sometimes may not literally mean you need to pass a Host header.
Fixing the headers fixed this. Print the exact request you are making and make sure all headers are correctly formatted.

Passenger 3.0.17 + Nginx 1.2.4 + "Content-Length" Header = 502 Bad Gateway

I have just run across an issue where setting response.headers['Content-Length'] in a Rails 3.2.2 application causes Nginx to throw a "502 Bad Gateway" error.
I have an action in a controller that uses the send_data method to send raw JPEG data contained within a variable. Before, I had a problem with some browsers not downloading the entire image being sent and discovered that no Content-Length header is being sent, so I decided to use the .bytesize property of the variable containing the JPEG data as the Content-Length.
This works fine in development (using Unicorn) and there is now a Content-Length header where there wasn't one before, but in production where I'm using Nginx and Passenger, I get the afore-mentioned 502 Bad Gateway. Also, in the Nginx error log, I see:
[error] 30574#0: *1686 upstream prematurely closed connection while reading response header from upstream
There are no matching entries in the Rails production log, which tells me the application is fine.
I've commented out the line where I set the Content-Length header, and the problem went away. I'm still testing whether I actually need to send a Content-Length header, but meanwhile, I thought I might post this out of curiosity to see if anyone has any thoughts.
AHA! I had to convert the size to a string by adding the .to_s method. So, my final result is
response.headers['Content-Length'] = photo_data.bytesize.to_s
send_data photo_data, :type => :jpg, :filename => 'file_name.jpg', :disposition => 'attachment'
So, it would seem that it is okay to send the Content-Length header on Nginx/Passenger, but Passenger chokes if it's not explicitly a string.

Does the name of an HTTP status code matter

Say I'm sending some HTTP status code in PHP, do I actually need to do
header('HTTP/1.1 301 Moved Permanently');
or is it enough to
header('HTTP/1.1 301 FooBar');
I once did this in a quick and dirty reverse proxy, where I could only get the code, not the message, from a CURL response and sent it back with FooBar as message. This appeared to work fine.
Via the spec:
The individual values of the numeric status codes defined for
HTTP/1.1, and an example set of corresponding Reason-Phrase's, are
presented below. The reason phrases listed here are only
recommendations -- they MAY be replaced by local equivalents without
affecting the protocol.

Response does not start with HTTP

Attached Firefox to fiddler and got following error. What would cause this error?
Interesting thing to note is that the HTTP header is getting rendered on the page
So Fiddler says that there is a protocol violation because response does not start with HTTP. But the HTTP response is rendered on page.
it is likely that some page content, especially one that has a blank line, is displayed before the HTTP header info is displayed. In such case, the browser will think it was the end of the HTTP header section and render those characters as content.
(your attachment's link is broken now so can't see any info there)
You can use telnet to see precisely what the server is returning. If you are running the server on port 800, try this:
$ telnet hostname 800
GET / HTTP/1.0
(You need to hit enter twice after the GET line. You can also add headers at that point if you need to.)
and assuming a leading blank line is the problem, you'd see something like
(blank line)
HTTP/1.1 200 OK
Various-headers: here
The server is not sending things out correctly. A valid HTTP response would be the HTTP headers, followed by an empty line and then the content. In this case, it seems likely that this was not followed. If there was an empty line before the HTTP headers, the HTTP headers would just be treated like content and rendered accordingly.

Resources