3

Im trying to create a simple HTTP server that will receive POST messages and provide a simple response. Im using the standard HTTPServer with python. The client connects using a session() which should use a persistent connection but after each POST I see the message below in the debug that the connection is dropping.

INFO:urllib3.connectionpool:Resetting dropped connection:

DEBUG:urllib3.connectionpool:"GET / HTTP/1.1" 200 None

The client works properly when I try it with Apache so I believe the issue is in my simple server configuration. How can I configure the simple http server to work with persistent connections?

Simple Server Python Code:

from http.server import HTTPServer, BaseHTTPRequestHandler
from io import BytesIO
import time
import datetime
import logging


class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def _set_response(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header("Connection", "keep-alive")
        self.send_header("keep-alive", "timeout=5, max=30")
        self.end_headers()

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'Hello, world!')

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)

        curr_time = datetime.datetime.now()
        data = ('{"msgid":"0x0002", "timestamp": "'+ str(curr_time) +'", "message":"Test http response from Raspberry Pi HTTP server"}').encode()

        self.send_response(200)
        self.end_headers()
        response = BytesIO()
        #response.write(b'This is POST request. ')
        #response.write(b'Received: ')
        response.write(data)
        self.wfile.write(response.getvalue())

print("Simple HTTP Server running...")
logging.basicConfig(level=logging.DEBUG)
httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()

Client Python code:

#!/usr/bin/env python

# Using same TCP connection for all HTTP requests

import os
import json
import time
import datetime
import logging
import requests
from requests.auth import HTTPBasicAuth

logging.basicConfig(level=logging.DEBUG)
start_time = time.time()

def get_data(limit):
    session = requests.Session()
    url = "http://localhost:8000"

    for i in range(10):
        curr_time = datetime.datetime.now()
        data = '{"msgid":"0x0001", "timestamp": "'+ str(curr_time) +'", "message":"Test http message from Raspberry Pi"}'

        print("Sending Data: " + data)

        response = session.post(url.format(limit), data)
        #response_dict = json.loads(response.text)
        print("Received Data: " + response.text)

if __name__ == "__main__":
  limit = 1
  get_data(limit)
  print("--- %s seconds ---" % (time.time() - start_time))

1 Answer 1

3

You aren't actually setting the Connection header in your POST handler. In order for persistent connections to work, you'll also need to set the Content-Length header in the response so that client knows how many bytes of the HTTP body to read before reusing the connection.

Try this POST handler, adapted from your code:

   def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)

        # Process the request here and generate the entire response
        response_data = b'{"stuff": 1234}'

        # Send the response
        self.send_response(200)
        self.send_header("Connection", "keep-alive")
        self.send_header("Content-Length", str(len(response_data)))
        self.end_headers()

        # Write _exactly_ the number of bytes specified by the
        # 'Content-Length' header
        self.wfile.write(response_data)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.