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()