Python Web Server Gateway Interface (或簡稱WSGI,讀作“wizgy” )。
WSGI允許開發者將選擇web框架和web伺服器分開。可以混合匹配web伺服器和web框架,選擇一個適合的配對。例如,可以在Gunicorn 或 Nginx/uWSGI 或 Waitress上運行 Django, Flask, 或 Pyramid。真正的混合匹配,得益於WSGI同時支援伺服器和架構.
web伺服器必須具備WSGI接口,所有的現代Python Web框架都已具備WSGI接口,它讓你不對代碼作修改就能使伺服器和特點的web框架協同工作。
WSGI由網頁伺服器支持,而web框架允許你選擇適合自己的配對,但它同樣對於伺服器和框架開發者提供便利使他們可以專注於自己偏愛的領域和專長而不至於相互牽制。其他語言也有類似介面:java有Servlet API,Ruby 有 Rack。
WSGI介面定義非常簡單,它只要求Web開發者實作一個函數,就可以回應HTTP請求。讓我們來看一個最簡單的Web版本的「Hello World!」:
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')])return 'Hello World!'
上面的 application( ) 函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:
environ:一個包含所有HTTP請求資訊的dict物件;
#start_response:一個傳送HTTP回應的函式。
整個application( )函數本身沒有涉及到任何解析HTTP的部分,也就是說,把底層web伺服器解析部分和應用程式邏輯部分進行了分離,這樣開發者就可以專心做一個領域了.
application( )函數必須由WSGI伺服器來呼叫。有很多符合WSGI規範的伺服器。而我們此時的web伺服器專案的目的就是要做一個極可能解析靜態網頁也可以解析動態網頁的伺服器
實作程式碼:
import time,multiprocessing,socket,os,reclass MyHttpServer(object):def __init__(self): serveSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serveSocket = serveSocket self.HTMLPATH = './html'def bind(self,port=8000): self.serveSocket.bind(('',port))def start(self): self.serveSocket.listen()while True: clientSocket, clientAddr = self.serveSocket.accept() print(clientSocket) multiprocessing.Process(target=self.serveHandler, args=(clientSocket, clientAddr)).start() clientSocket.close()def serveHandler(self,clientSocket,clientAddr):try: recvData = clientSocket.recv(1024).decode('gbk') fileName = re.split(r' +', recvData.splitlines()[0])[1] filePath = self.HTMLPATHif fileName.endswith('.py'):try: pyname=fileName[1:-3]# 导入 pyModule = __import__(pyname) env={} responseBody = pyModule.application(env,self.startResponse) responseLine = self.responseLine responseHeader = self.responseHeaderexcept ImportError: responseLine = 'HTTP/1.1 404 NOT FOUND' responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date: %s' % time.ctime() responseBody = '<h1>很抱歉,服务器中找不到你想要的内容<h1>'else:if '/'== fileName: filePath += '/index.html'else: filePath += fileNametry: file = None file =open(filePath,'r',encoding='gbk') responseBody = file.read() responseLine = 'HTTP/1.1 200 OK' responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date:%s' % time.ctime()except FileNotFoundError: responseLine = 'HTTP/1.1 404 NOT FOUND' responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date:%s' % time.ctime() responseBody = '很抱歉,服务器中找不到你想要的内容'finally:if (file!=None) and (not file.closed): file.close()except Exception as ex: responseLine = 'HTTP/1.1 500 ERROR' responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date: %s' % time.ctime() responseBody = '服务器正在维护中,请稍后再试。%s'%exfinally: senData = responseLine + os.linesep + responseHeader + os.linesep + os.linesep + responseBody print(senData) senData = senData.encode('gbk') clientSocket.send(senData)if (clientSocket!=None) and ( not clientSocket._closed): clientSocket.close()def startResponse(self,status,responseHeaders): self.responseLine = status self.responseHeader = ''for k,v in responseHeaders: kv = k + ':' + v + os.linesep self.responseHeader += kvif __name__ == '__main__': server = MyHttpServer() server.bind(8000) server.start()
伺服器中存在的html的檔案:
index.html
<html><head><title>首页-毕业季</title><meta http-equiv=Content-Type content="text/html;charset=gbk"></head><body>我们仍需共生命的慷慨与繁华相爱,即使岁月以刻薄和荒芜相欺。</body></html>
#biye.html
<!DOCTYPE html><html lang="en"><head><meta charset="gbk"><title>毕业季</title></head><body>![](http://localhost:51017/day18/html/biyeji.png)<br>当年以为六月不过也很平常<br>当自己真正经历了毕业<br>才知道偶尔看到六月毕业季等字里所流露的种种想要重温却不敢提及的回忆<br>毕业了<br>那个夏天,我的毕业季,我的青春年少<br>六月<br>有人笑着说解脱,有人哭着说不舍<br>那年,<br>你对我说的你好<br>在不知不觉中<br>变成了<br>再见。</body></html>
import timedef application(env,startResponse): status = 'HTTP/1.1 200 OK' responseHeaders = [('Server','bfe/1.0.8.18'),('Date','%s'%time.ctime()),('Content-Type','text/plain')] startResponse(status,responseHeaders) responseBody = str(time.ctime())return responseBody