I'm trying to build a simple HTTP web server that serves a single file (index.html) over a persistent TCP connection. Specifically, I want the browser to be able to send multiple HTTP requests over the same TCP socket (only one socket at a time). To implement this, I've written the following code:
from socket import *
import sys
serverPort = int(sys.argv[1])
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("localhost", serverPort))
serverSocket.listen(1)
print("Listening on port " + str(serverPort) + "...")
while True:
connectionSocket, addr = serverSocket.accept()
while True:
request = connectionSocket.recv(4096)
if not request:
print("BROKEN")
break
request = request.decode()
headers = request.split("\n")
requestedFile = headers[0].split(" ")[1]
if (requestedFile[0] == "/"):
requestedFile = requestedFile[1:]
fileInput = open(requestedFile)
content = fileInput.read()
fileInput.close()
response = "HTTP/1.1 200 OK\r\n" + "Connection: Keep-Alive\r\n\r\n" + content
connectionSocket.send(response.encode())
connectionSocket.close()
There are two loops. The outer loop creates the socket, and also closes it once the inner loop terminates. The inner loop receives requests and generates responses. When I run the server on port 1000 and connect in my browser (Microsoft Edge) at 'http://localhost:1000/index.html' the HTML page is displayed properly, and my browser's network tab doesn't indicate any activity. But the loading circle on the tab continues spinning forever, making it seem like something hasn't loaded properly. What might be causing this?
Thank you!
This happens because the browser does not know how long the content body is. You can either provide a Content-Length
header in your response or you can close the connection to let the browser know that the complete response has been sent.
from socket import *
import sys
serverPort = int(sys.argv[1])
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("localhost", serverPort))
serverSocket.listen(1)
print("Listening on port " + str(serverPort) + "...")
while True:
# Create socket
connectionSocket, addr = serverSocket.accept()
while True:
# Get request from socket
request = connectionSocket.recv(4096)
if not request:
print("BROKEN")
break
# Parse request to determine requested file
request = request.decode()
headers = request.split("\n")
requestedFile = headers[0].split(" ")[1]
if (requestedFile[0] == "/"):
requestedFile = requestedFile[1:]
# Read requested file and generate/send response
fileInput = open(requestedFile)
content = fileInput.read()
fileInput.close()
response = "HTTP/1.1 200 OK\r\n" + "Connection: Keep-Alive\r\n" + "Content-Length: {}\r\n\r\n".format(len(content)) +content
connectionSocket.send(response.encode())
connectionSocket.close()
References: https://www.w3.org/Protocols/HTTP/1.0/draft-ietf-http-spec.html#BodyLength