What, at the bare minimum, is required for an HTTP request?

Http

Http Problem Overview


I'm trying to issue a GET command to my local server using netcat by doing the following:

echo -e "GET / HTTP/1.1\nHost: localhost" | nc localhost 80

Unfortunately, I get a HTTP/1.1 400 Bad Request response for this. What, at the very minimum, is required for a HTTP request?

Http Solutions


Solution 1 - Http

if the request is: "GET / HTTP/1.0\r\n\r\n" then the response contains header as well as body, and the connection closes after the response.

if the request is:"GET / HTTP/1.1\r\nHost: host:port\r\nConnection: close\r\n\r\n" then the response contains header as well as body, and the connection closes after the response.

if the request is:"GET / HTTP/1.1\r\nHost: host:port\r\n\r\n" then the response contains header as well as body, and the connection will not close even after the response.

if your request is: "GET /\r\n\r\n" then the response contains no header and only body, and the connection closes after the response.

if your request is: "HEAD / HTTP/1.0\r\n\r\n" then the response contains only header and no body, and the connection closes after the response.

if the request is: "HEAD / HTTP/1.1\r\nHost: host:port\r\nConnection: close\r\n\r\n" then the response contains only header and no body, and the connection closes after the response.

if the request is: "HEAD / HTTP/1.1\r\nHost: host:port\r\n\r\n" then the response contains only header and no body, and the connection will not close after the response.

Solution 2 - Http

It must use CRLF line endings, and it must end in \r\n\r\n, i.e. a blank line. This is what I use:

printf 'GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n' |
  nc www.example.com 80

Additionally, I prefer printf over echo, and I add an extra header to have the server close the connection, but those aren’t needed.

Solution 3 - Http

See Wiki: HTTP Client Request (Example).

Note the following:

>> A client request (consisting in this case of the request line and only one header) is followed by a blank line, so that the request ends with a double newline, each in the form of a carriage return followed by a line feed. The "Host" header distinguishes between various DNS names sharing a single IP address, allowing name-based virtual hosting. While optional in HTTP/1.0, it is mandatory in HTTP/1.1.

The absolute minimum (if removing the Host is allowed ;-) is then GET / HTTP/1.0\r\n\r\n.

Happy coding

Solution 4 - Http

I was able to get a response from my Apache server with only the requested document, no response header, with just

GET /\r\n

If you want response headers, including the status code, you need one of the other answers here though.

Solution 5 - Http

The fact of the 400 Bad Request error itself does not imply that your request violates HTTP. The server very well could be giving this response for another reason.

As far as I know the absolute minimum valid HTTP request is:

GET / HTTP/1.0\r\n\r\n

Solution 6 - Http

Please, please, please, do not implement your own HTTP client without first reading the relevant specs. Please read and make sure that you've fully understood at least RFC 2616. (And if you're ambitious, RFC 7230 through 7235).

While HTTP looks like an easy protocol, there are actually a number of subtle points about it. Anyone who has written an HTTP server will tell you about the workarounds he had to implement in order to deal with incorrect but widely deployed clients. Unless you're into reading specifications, please use a well-established client library; Curl is a good choice, but I'm sure there are others.

If you're going to implement your own:

  • do not use HTTP/0.9;
  • HTTP/1.0 requires the query line and the empty line;
  • in HTTP/1.1, the Host: header is compulsory in addition to the above.

Omitting the Host: header in HTTP/1.1 is the most common cause of 400 errors.

Solution 7 - Http

Solution 8 - Http

The really REALLY BARE minimum, is not using netcat, but using bash itself:

user@localhost:~$ exec 3<>/dev/tcp/127.0.0.1/80
user@localhost:~$ echo -e "GET / HTTP/1.1\n" >&3
user@localhost:~$ cat <&3
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.6
Date: Mon, 13 Oct 2014 17:55:55 GMT
Content-type: text/html; charset=UTF-8
Content-Length: 514

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
</ul>
<hr>
</body>
</html>
user@localhost:~$ 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNaftuli KayView Question on Stackoverflow
Solution 1 - HttpAbhishek OzaView Answer on Stackoverflow
Solution 2 - HttpJosh LeeView Answer on Stackoverflow
Solution 3 - Httpuser166390View Answer on Stackoverflow
Solution 4 - HttpjfkleinView Answer on Stackoverflow
Solution 5 - HttpwberryView Answer on Stackoverflow
Solution 6 - HttpjchView Answer on Stackoverflow
Solution 7 - HttpDorView Answer on Stackoverflow
Solution 8 - HttpMarcelView Answer on Stackoverflow