|
@@ -0,0 +1,179 @@
|
|
|
+import socket
|
|
|
+import threading
|
|
|
+import datetime
|
|
|
+import os
|
|
|
+from pathlib import Path
|
|
|
+
|
|
|
+htmlTemplate='''<!DOCTYPE html>
|
|
|
+<html>
|
|
|
+ <head>
|
|
|
+ <title>{title}</title>
|
|
|
+ </head>
|
|
|
+ <body>{content}</body>
|
|
|
+</html>
|
|
|
+'''
|
|
|
+
|
|
|
+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+'<li><a href="%s">%s</a></li>' %(self.URL+i,i)
|
|
|
+ if self.URL!='/':
|
|
|
+ content='<li><a href="../">../</a></li>'+content
|
|
|
+ title='Index of '+self.URL
|
|
|
+ content='<h1> '+title+'</h1><hr/>'+'<ul>'+content+'</ul>'
|
|
|
+ return htmlTemplate.format(title=title,content=content)
|
|
|
+
|
|
|
+ elif self.statusCode=='404':
|
|
|
+ return htmlTemplate.format(title='404 Not Found',content='<h1>404 Not Found</h1>')
|
|
|
+ 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='<h1>500 Internal Server Error</h1>')
|
|
|
+ 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()
|