Skip to content

Instantly share code, notes, and snippets.

@alastairparagas
Created April 17, 2016 23:47
Show Gist options
  • Select an option

  • Save alastairparagas/6efd7d2758563043b6d7784d789a1463 to your computer and use it in GitHub Desktop.

Select an option

Save alastairparagas/6efd7d2758563043b6d7784d789a1463 to your computer and use it in GitHub Desktop.
import socket
import sys
import mimetypes
import threading
import os
import time
def getFileMimetype(absoluteFilePath):
"""
Gets the HTTP mime type of a file located at provided file path
"""
return mimetypes.guess_type(absoluteFilePath)[0]
def getFileLastModified(absoluteFilePath):
"""
Gets the HTTP content type of a file located at provided file path
"""
return time.strftime("%a, %d %b %Y %H:%M:%S GMT",
time.gmtime(getLastModifiedTime(absoluteFilePath)))
def generateHeaders(statusCode=200,
contentLength=0,
contentType="text/html",
lastModified=""):
"""
Generates HTTP headers as a string
"""
headerText = []
if statusCode == 200:
headerText.append("HTTP/1.1 200 OK\r\n")
elif statusCode == 400:
headerText.append("HTTP/1.1 404 Not Found\r\n")
else:
headerText.append("HTTP/1.1 400 Bad Request\r\n")
if len(lastModified) > 0:
headerText.append("".join(["Last-Modified: ", lastModified, "\r\n"]))
headerText.append("".join(["Content-Type: ", contentType, "\r\n"]))
headerText.append("".join(["Content-Length: ", str(contentLength), "\r\n"]))
headerText.append("Server: Alastair's Python Server\r\n")
headerText.append("Connection: close\r\n\n")
return "".join(headerText)
def handleRequest(tcpCliSock, data):
"""
Handle proxy requests
"""
# Extract the requested resource/URL from the given HTTP data
dataSplit = data.split()[1]
print dataSplit
filename = dataSplit.partition("/")[2]
print filename
try:
# Check whether the file exist in the cache
f = open(filename, "r")
outputData = f.readlines()
f.close()
outputData = "".join(outputData)
# ProxyServer finds a cache hit and generates a response message
tcpCliSock.send(
generateHeaders(contentLength=len(outputData),
contentType=getFileMimeType(filename),
lastModified=time.ctime(os.stat(filename)[8]))
)
tcpCliSock.send(outputData)
tcpCliSock.close()
print 'Read from cache'
# Error handling for file not found in cache
except IOError:
try:
# Create a socket on the proxyserver
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = filename.replace("www.", "", 1)
print hostname
# Connect to the socket to port 80
clientSock.connect((hostname, 80))
print "Connected to host: " + hostname + ", port 80"
# Create a temporary file on this socket and ask
# port 80 for the file requested by the client
fileobj = clientSock.makefile('r', 0)
fileobj.write("GET " + "http://" + filename + " HTTP/1.1\n" +
"Connection: close\n\n")
# Read the response into buffer
outputData = fileobj.readlines()
outputData = "".join(outputData)
print outputData
fileobj.close()
# Create a new file in the cache for the requested file.
# Also send the response in the buffer to client socket
# and the corresponding file in the cache
tmpFile = open("./" + filename, "wb")
tmpFile.write(outputData)
tmpFile.close()
tcpCliSock.send(
generateHeaders(contentLength=len(outputData),
contentType=getFileMimetype(filename))
)
tcpCliSock.send(outputData)
tcpCliSock.close()
fileobj.close()
except Exception:
notFoundMessage = """
<!DOCTYPE HTML>
<html>
<head><title>404 Not Found</title></head>
<body>404 Not Found</body>
</html>
"""
tcpCliSock.send(
generateHeaders(statusCode=404, contentLength=len(notFoundMessage))
)
tcpCliSock.send(notFoundMessage)
tcpCliSock.close()
if len(sys.argv) <= 1:
print ('Usage : "python ProxyServer.py server_ip"\n' +
'[server_ip : The IP Address Of Proxy Server]')
sys.exit(2)
# Create a server socket, bind it to a port and start listening
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(("", 8000))
tcpSerSock.listen(2)
while 1:
# Start receiving data from the client
print 'Ready to serve...'
# Accept an HTTP message with a maximum possible request size of
# 8192 bytes = 8KB. This HTTP message will look something like
# GET www.google.com
tcpCliSock, addr = tcpSerSock.accept()
print 'Received a connection from:', addr
message = tcpCliSock.recv(8192)
print message
requestThread = threading.Thread(target=handleRequest, args=(tcpCliSock, message))
requestThread.start()
tcpSerSock.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment