天天看點

python 伺服器開發 ----了解WSGI協定

看了一些WSGI協定後,對其中的邏輯有些模糊,是以按照WSGI協定,寫了一個簡易的動态web伺服器。

什麼是WSGI協定?

自行百度

web動态伺服器實作邏輯

廢話少說先上個圖:

python 伺服器開發 ----了解WSGI協定

需要注意的是:

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)
           

繼續閱讀