#1.瀏覽器請求動態頁面過程html
#2.WSGI Python Web Server Gateway Interface (或簡稱 WSGI,讀做「wizgy」)。java
WSGI容許開發者將選擇web框架和web服務器分開。能夠混合匹配web服務器和web框架,選擇一個適合的配對。好比,能夠在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上運行 Django, Flask, 或 Pyramid。真正的混合匹配,得益於WSGI同時支持服務器和架構.web
web服務器必須具有WSGI接口,全部的現代Python Web框架都已具有WSGI接口,它讓你不對代碼做修改就能使服務器和特色的web框架協同工做。瀏覽器
WSGI由web服務器支持,而web框架容許你選擇適合本身的配對,但它一樣對於服務器和框架開發者提供便利使他們能夠專一於本身偏心的領域和專長而不至於相互牽制。其餘語言也有相似接口:java有Servlet API,Ruby 有 Rack。 #3.定義WSGI接口 WSGI接口定義很是簡單,它只要求Web開發者實現一個函數,就能夠響應HTTP請求。咱們來看一個最簡單的Web版本的「Hello World!」:bash
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return 'Hello World!'
複製代碼
上面的 application( ) 函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:服務器
整個**application( )**函數自己沒有涉及到任何解析HTTP的部分,也就是說,把底層web服務器解析部分和應用程序邏輯部分進行了分離,這樣開發者就能夠專心作一個領域了.架構
**application( )**函數必須由WSGI服務器來調用。有不少符合WSGI規範的服務器。而咱們此時的web服務器項目的目的就是作一個很可能解析靜態網頁還能夠解析動態網頁的服務器app
實現代碼:框架
import time,multiprocessing,socket,os,re
class 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.HTMLPATH
if fileName.endswith('.py'):
try:
pyname=fileName[1:-3]
# 導入
pyModule = __import__(pyname)
env={}
responseBody = pyModule.application(env,self.startResponse)
responseLine = self.responseLine
responseHeader = self.responseHeader
except 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 += fileName
try:
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'%ex
finally:
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 += kv
if __name__ == '__main__':
server = MyHttpServer()
server.bind(8000)
server.start()
複製代碼
服務器中存在的html的文件:socket
<html>
<head>
<title>首頁-畢業季</title>
<meta http-equiv=Content-Type content="text/html;charset=gbk">
</head>
<body>咱們仍需共生命的慷慨與繁華相愛,即便歲月以刻薄和荒蕪相欺。
</body>
</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>
複製代碼
###mytime.py文件
import time
def 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
複製代碼
####訪問結果:
''' 自定義的符合wsgi的框架 '''
import time
class Application(object):
def __init__(self, urls):
'''框架初始化的時候須要獲取路由列表'''
self.urls = urls
def __call__(self, env, startResponse):
''' 判斷是靜態資源仍是動態資源。 設置狀態碼和響應頭和響應體 :param env: :param startResponse: :return: '''
# 從請求頭中獲取文件名
fileName = env.get('PATH_INFO')
# 判斷靜態仍是動態
if fileName.startwith('/static'):
fileName = fileName[7:]
if '/' == fileName:
filePath += '/index.html'
else:
filePath += fileName
try:
file = None
file = open(filePath, 'r', encoding='gbk')
responseBody = file.read()
status = 'HTTP/1.1 200 OK'
responseHeaders = [('Server', 'ererbai')]
except FileNotFoundError:
status = 'HTTP/1.1 404 Not Found'
responseHeaders = [('Server', 'ererbai')]
responseBody = '<h1>找不到<h1>'
finally:
startResponse(status, responseHeaders)
if (file != None) and (not file.closed):
file.close()
else:
isHas = False # 表示請求的名字是否在urls中,True:存在,False:不存在
for url, func in self.urls:
if url == fileName:
responseBody = func(env, startResponse)
isHas = True
break
if isHas == False:
status = 'HTTP/1.1 404 Not Found'
responseHeaders = [('Server', 'ererbai')]
responseBody = '<h1>找不到<h1>'
startResponse(status, responseHeaders)
return responseBody
def mytime(env, startResponse):
status = 'HTTP/1.1 200 OK'
responseHeaders = [('Server', 'time')]
startResponse(status, responseHeaders)
responseBody = str(time.ctime())
return responseBody
def mynews(env, startResponse):
status = 'HTTP/1.1 200 OK'
responseHeaders = [('Server', 'news')]
startResponse(status, responseHeaders)
responseBody = str('xx新聞')
return responseBody
'''路由列表'''
urls = [
('/mytime', mytime),
('/mynews', mynews)
]
application = Application(urls)
複製代碼