1.瀏覽器請求動態頁面過程 2.WSGI Python Web Server Gateway Interface (或簡稱 WSGI,讀作“wizgy”)。 WSGI允許開發者將選擇web框架和web伺服器分開。可以混合匹配web伺服器和web框架,選擇一個適合的配對。比如,可以在Gunicorn ...
1.瀏覽器請求動態頁面過程
2.WSGI
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伺服器支持,而web框架允許你選擇適合自己的配對,但它同樣對於伺服器和框架開發者提供便利使他們可以專註於自己偏愛的領域和專長而不至於相互牽制。其他語言也有類似介面:java有Servlet API,Ruby 有 Rack。
3.定義WSGI介面
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,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的文件:
- 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>
biyeji.png
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
訪問結果:
首頁
biye.html
mytime.py
'''
自定義的符合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)
學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入學習交流群
626062078,我們一起學Python!