看了一些WSGI協定後,對其中的邏輯有些模糊,是以按照WSGI協定,寫了一個簡易的動态web伺服器。
什麼是WSGI協定?
自行百度
web動态伺服器實作邏輯
廢話少說先上個圖:
需要注意的是:
1、application是應用程式中對web伺服器提供的唯一接口,他接受兩個參數:
1)env:伺服器傳遞給application的請求資訊,形式如下:
env = {
"PATH_INFO": file_name[1:],#請求資源的路徑
"METHOD": method #請求方法get、post
}
2)start_response:web伺服器提供的一個函數,沒有傳回值,application架構通過調用該函數把headers和status傳遞給伺服器
application傳回值:response_body
代碼:
server:
import socket
import sys
import os
import re
from threading import Thread
HTML_ROOT_DIR=os.getcwd()+'/html/'
WSGI_DIR=os.getcwd()+"/wsgipython/"
class HTTPServer(object):
"""
statict http server
"""
def __init__(self,addr,port,application):
self.server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.server_socket.bind((addr,port))
self.server_socket.listen(128)
self.server_socket_count=0
self.application=application
def start_response(self,status,headers):
respones_headers="HTTP/1.1"+status+"\r\n"
for header in headers:
respones_headers+="%s:%s\r\n" % header
self.response_headers=respones_headers
def Handle_client(self,conn,addr):
data=conn.recv(1024).decode("utf-8")
# file_name=re.match()
# print(data)
data_lines=data.splitlines()
file_name = re.match(r"\w+ +(/[^ ]*) ", data_lines[0]).group(1)
method = re.match(r"(\w+) +/[^ ]* ", data_lines[0]).group(1)
env = {
"PATH_INFO": file_name[1:],
"METHOD": method
}
response_body=self.application(env,self.start_response)
response=self.response_headers+"\r\n"+response_body
print(response)
conn.send(response.encode("utf-8"))
conn.close()
def start(self):
sys.path.insert(1,WSGI_DIR)
while True:
conn,addr=self.server_socket.accept()
self.server_socket_count+=1
t=Thread(target=self.Handle_client,args=(conn,addr))
t.start()
# print(self.server_socket_count)
if __name__=="__main__":
"python dynamic_web_server MyWebFramework:app"
if len(sys.argv)<2:
sys.exit("please input like 'python dynamic_web_server MyWebFramework:app'")
frame_name,application_name=sys.argv[1].split(":")
m=__import__(frame_name)
application=getattr(m,application_name)
httpserver=HTTPServer("127.0.0.1",8000,application)
httpserver.start()
application framework:
import time
import os
HTML_ROOT_DIR=os.getcwd()+'/html/'
class Application(object):
"""
"""
def __init__(self,urls):
self.urls=urls
def __call__(self, env,start_response):
path_info=env.get("PATH_INFO","/")
# print(path_info)
if path_info.startswith("static/") or path_info.startswith("/"):
# print("hhh")
return static_page(env,start_response)
else:
for path,handler in self.urls:
if path_info==path:
return handler(env,start_response)
return error(env,start_response)
def static_page(env,start_response):
status = " 200 OK"
headers = [
("Server", "My server\r\n")
]
try:
f=open(HTML_ROOT_DIR+"index.html",'rb')
except IOError:
return error(env,start_response)
else:
start_response(status,headers)
response_body=f.read()
# print(response_body)
return response_body.decode("utf-8")
def error(env,start_response):
status = "HTTP/1.1 404 Not Found\r\n"
headers = [("Server","My server\r\n")]
response_body = "The file is not found!"
start_response(status,headers)
return response_body
def login(env,start_response):
status = " 200 OK"
headers = [
("Content-Type", "text/plain")
]
start_response(status, headers)
return "login successful"
def say_hello(env,start_response):
status = " 200 OK"
headers = [
("Content-Type", "text/plain")
]
start_response(status,headers)
return "hello world!"
def show_time(env,start_response):
status = " 200 OK"
headers = [
("Content-Type", "text/plain")
]
return time.ctime()
urls=[
("login",login),
("sayhello",say_hello),
("showtime",show_time)
]
app=Application(urls)