Robert Tupelo-Schneck
Robert Tupelo-Schneck

Reputation: 10544

How can I get Jetty to return an error response instead of assuming an HTTP/0.9 request?

A broken HTTP client sent some requests to our Jetty-based HTTP server with a newline in the URL. Jetty sees this as an HTTP/0.9 request, truncates the URL at the newline, ignores the request headers, and sends back a response with no headers or status line.

I believe this is mostly correct according to spec, although Jetty doesn't require CRLF and will happily do this for requests other than GET. But newer specs note that HTTP/0.9 requests mainly indicate confused clients. In our case, the client (and we) could have avoided some confused troubleshooting if an error message had been sent instead.

How can I get Jetty to return an error response to requests with a newline in the URL? I'm happy to use either Jetty-level configuration or webapp-level code.

Upvotes: 0

Views: 3003

Answers (2)

Robert Tupelo-Schneck
Robert Tupelo-Schneck

Reputation: 10544

HttpServletRequest#getProtocol() will return an empty String for HTTP/0.9 requests in Jetty 8. Thus a simple filter can return a Bad Request response for such requests.

As the other answer indicates, HTTP/0.9 requests are no longer supported in recent versions of Jetty 9.

Upvotes: 0

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49462

First, support for HTTP/0.9 has been completely removed in Jetty 9.3+.

Lets see what the behavior is ...

Jetty Distribution 9.2.7.v20150116, running demo-base:

Normal HTTP/1.0 Request:

$ printf "GET / HTTP/1.0\r\n\r\n" | nc localhost 8080
HTTP/1.1 200 OK
Set-Cookie: visited=yes
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Accept-Ranges: bytes
Content-Type: text/html
Last-Modified: Sat, 17 Jan 2015 00:25:03 GMT
Content-Length: 2773
Server: Jetty(9.2.7.v20150116)

<html xmlns=\ "http://www.w3.org/1999/xhtml\" xml:lang=\"en\">

Got the headers there, looks like HTTP/1.0 response headers too.

Normal HTTP/1.1 Request:

$ printf "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" | nc localhost 8080
HTTP/1.1 200 OK
Set-Cookie: visited=yes
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Accept-Ranges: bytes
Content-Type: text/html
Last-Modified: Sat, 17 Jan 2015 00:25:03 GMT
Content-Length: 2773
Connection: close
Server: Jetty(9.2.7.v20150116)

<html xmlns=\ "http://www.w3.org/1999/xhtml\" xml:lang=\"en\">

Looks normal as well. Even includes the HTTP/1.1 specific headers.

Now lets try HTTP/1.0 with embedded CRLF:

 $ printf "GET /\r\nHTTP/1.0\r\n\r\n" | nc localhost 8080
 <html xmlns=\ "http://www.w3.org/1999/xhtml\" xml:lang=\"en\">

No response headers.

Why is this happening?

Well, there's no HTTP Version that Jetty can determine, so there's no valid set of headers it can respond with. So it responds with no headers. Which surprisingly is how HTTP spec prior to 1.0 behaved.

Now lets try Jetty Distribution 9.3.x, and the demo-base configuration with the same CRLF issue.

$ printf "GET /\r\nHTTP/1.0\r\n\r\n" | nc localhost 8080
HTTP/1.1 400 HTTP/0.9 not supported
Content-Length: 0
Connection: close
Server: Jetty(9.3.0-SNAPSHOT)

Now, in the modern era, with HTTP/2 just around the corner, this makes a lot more sense.

Upvotes: 1

Related Questions