3

Im currently creating a python socket http server, and I'm working on my GET and POST requests. I got my GET implementation working fine, but the body element of the POST requests won't show up. Code snippet:

self.host = ''
self.port = 8080

self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.listener.bind((self.host, self.port))
self.listener.listen(1)

while True:

        client_connection, client_address = self.listener.accept()
        request = client_connection.recv(2048)
        print request

This code yields the http header after processing the post request from the webpage:

POST /test.txt HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Origin: http://localhost:8080
Content-Length: 21
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17
Referer: http://localhost:8080/
Accept-Language: nb-no
Accept-Encoding: gzip, deflate

But there is no body, so the question is why am i not receiving the http body when i know it is sent?

Thanks!

mmoe
  • 95
  • 1
  • 2
  • 7
  • The question is: why aren't you showing the CLIENT code, where the POST was originally built? – Marc B Sep 15 '16 at 19:11
  • hi @MarcB the project is for a class assignment, and the client side is already implemented. I am only to implement a server side to handle the GET and POST requests. So i am to assume its the server side which got errors – mmoe Sep 15 '16 at 19:26
  • what errors? the server just spits out what it received. if it's not receiving a post body, perhaps you should check if the client is actually working properly. – Marc B Sep 15 '16 at 19:27
  • i've tested it through a java program, and i can assure you the body is sent. in the output above i did a post request on a 21 character long sentence, and as you can see the content-length parameter is 21. Im just wondering if the header and body is sent in two different parts, or if the socket.recv function stops receiving after the header or something like that @MarcB – mmoe Sep 15 '16 at 19:47
  • tcp has no idea what http is. it doesn't need to, and shouldn't need to. while your http request can/will get split into multiple packets. it'd be HIGHLY unusual for it to be split EXACTLY where the header/body separator is, every single time. – Marc B Sep 15 '16 at 20:19

1 Answers1

3
while True:

        client_connection, client_address = self.listener.accept()
        request = client_connection.recv(2048)
        print request

recv does not read exactly 2048 bytes but it reads up to 2048 bytes. If some data arrive recv will return with the data even if more data might follow. My guess is that in your case the client is first sending the HTTP header and then the body. If NAGLE algorithms is off at the client side (common) it is likely that your first recv will only get the header and that you would need another recv for the body. This would explain what happens in your case: you get the header but not the body since you don't do another recv.

But even that would be a too simple implementation which will go wrong sooner or later. To make it correctly you should implement the HTTP protocol correctly: first read the HTTP header which might need multiple recv if the header is large. Then you should parse the header, figure out the size of the body (Content-length header) and read the remaining bytes.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • perfect! it turned out the server stopped receiving data after the header, by calling a new socket.recv with the content-length did the trick! thanks – mmoe Sep 15 '16 at 20:11
  • @mmoe: but again. Don't count on it that you will get the full header with the first recv and the body with the next. The protocol underlying HTTP is TCP and this is a stream protocol which has no implicit message boundaries. The correct way is to just read data as long as you don't have found the end of the header (i.e. the empty line) – Steffen Ullrich Sep 16 '16 at 04:25