import socket
import threading
import datetime
import os
from pathlib import Path
htmlTemplate='''
{title}
{content}
'''
EXTS={'jpg' :'image/jpeg',
'jpeg':'image/jpeg',
'png' :'image/png',
'ico' :'image/icon',
'htm' :'text/html',
'html':'text/html',
'js' :'application:x-javascript',
'css' :'text/css',
'txt' :'text/plain'}
class Request(object):
def __init__(self,req):
self.__chips=req.split('\r\n')
self.__RLChips=self.__chips[0].split(' ')
self.method=self.__RLChips[0]
self.URL=self.__RLChips[1]
self.version=self.__RLChips[2]
self.headers=self.__getHeaders()
self.requestBody=self.__chips[-1]
def __getHeaders(self):
header=self.__chips[1:-2]
headerDict={}
for i in header:
key,value=i.split(': ',1)
headerDict[key]=value
return headerDict
class Response(object):
def __init__(self):
self.version='HTTP/1.1'
self.date=datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT')
self.contentType='text/html'
self.ext=''
def dealRequest(self,request):
self.version=request.version
self.URL=request.URL
self.path=os.path.join('www',request.URL[1:])
self.ext=self.path.split('.')[-1] if '.' in self.path else ''
self.statusCode,self.statusDesc=self.__ifExist()
self.content=self.__getContent()
self.contentType=self.__getType()
def __ifExist(self):
exist=os.path.exists(self.path)
if exist:
return ['200','OK']
else:
return ['404','Not Found']
def __getContent(self):
if self.statusCode=='200':
if Path(self.path).is_file():
with open(self.path,'rb') as f:
page=f.read()
try:
return page.decode('utf-8')
except:
return page
else:
content=''
if self.URL[-1]!='/':
self.redirect(self.URL+'/',tem=False)
return ''
for i in os.listdir(self.path):
if Path(os.path.join(self.path,i)).is_dir():
i=i+'/'
content=content+'%s' %(self.URL+i,i)
if self.URL!='/':
content='../'+content
title='Index of '+self.URL
content=' '+title+'
'+''
return htmlTemplate.format(title=title,content=content)
elif self.statusCode=='404':
return htmlTemplate.format(title='404 Not Found',content='404 Not Found
')
else:
return ''
def __getType(self):
if self.statusCode=='200' and Path(self.path).is_file():
return EXTS[self.ext] if self.ext in EXTS else 'text/plain'
else:
return 'text/html'
def redirect(self,url,tem=True):
if tem:
self.statusCode='302'
self.statusDesc='Moved Temporarily'
else:
self.statusCode='301'
self.statusDesc='Moved Permanently'
self.location=url
@property
def header(self):
statusLine=self.version+' '+self.statusCode+' '+self.statusDesc
baseHeader=statusLine+\
'\r\nDate: '+self.date+\
'\r\nContent-Type: '+self.contentType+\
'\r\nContent-Length: '+str(len(self.content))
if self.statusCode=='302' or self.statusCode=='301':
baseHeader=baseHeader+'\r\nLocation: '+self.location
return baseHeader+"\r\n\r\n"
def http(sock,addr):
buffer=b''
while True:
data=sock.recv(1024)
buffer=buffer+data
if len(data)<1024:
break
data=buffer.decode('utf-8')
if len(data)==0:
sock.close()
return ''
response=Response()
try:
request=Request(data)
response.dealRequest(request)
if request.URL=='/123456':
response.redirect('/index.html')
except:
response.statusCode='500'
response.statusDesc='Internal Server Error'
response.content=htmlTemplate.format(title='500 Internal Server Error',content='500 Internal Server Error
')
sock.send(response.header.encode('utf-8'))
if isinstance(response.content,bytes):
sock.send(response.content)
else:
sock.send(response.content.encode('utf-8'))
print(addr[0]+' === '+request.method+" === "+request.URL+" === "+response.statusCode)
sock.close()
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('0.0.0.0',5000))
s.listen(5)
print('httpserver running...')
while True:
sock,addr=s.accept()
t=threading.Thread(target=http,args=(sock,addr))
t.start()