欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WSGI 协议

程序员文章站 2022-07-15 11:23:12
...

在Python Web开发时经常会遇到WSGI,所以WSGI到底是什么呢?本文我们一起来揭开WSGI神秘的面纱!

先来看一下WSGI的介绍:

全称Python Web Server Gateway Interface,指定了web服务器和Python web应用或web框架之间的标准接口,以提高web应用在一系列web服务器间的移植性。

从以上介绍我们可以看出:

WSGI是一套接口标准协议/规范;
通信(作用)区间是Web服务器和Python Web应用程序之间;
目的是制定标准,以保证不同Web服务器可以和不同的Python程序之间相互通信
你可能会问,为什么需要WSGI?

首先,我们明确一下web应用处理请求的具体流程:

用户操作操作浏览器发送请求;
请求转发至对应的web服务器
web服务器将请求转交给web应用程序,web应用程序处理请求
web应用将请求结果返回给web服务器,由web服务器返回用户响应结果
浏览器收到响应,向用户展示
可以看到,请求时Web服务器需要和web应用程序进行通信,但是web服务器有很多种啊,Python web应用开发框架也对应多种啊,所以WSGI应运而生,定义了一套通信标准。试想一下,如果不统一标准的话,就会存在Web框架和Web服务器数据无法匹配的情况,那么开发就会受到限制,这显然不合理的。
WSGI 协议
既然定义了标准,那么WSGI的标准或规范是?

web服务器在将请求转交给web应用程序之前,需要先将http报文转换为WSGI规定的格式。

WSGI规定,Web程序必须有一个可调用对象,且该可调用对象接收两个参数,返回一个可迭代对象:

environ:字典,包含请求的所有信息
start_response:在可调用对象中调用的函数,用来发起响应,参数包括状态码,headers等
通过以上学习,一起实现一个简单WSGI服务吧

首先我们编写一个符合WSGI协议标准的http处理函数

def application(env, start_response):
    start_response("200 OK", [("Content-Type", "text/html;charset=utf-8")])
    file_name = env["PATH_INFO"] 
    if file_name == "/index.py":
         return "这是主页"
    elif file_name == "/login.py":
        return "这个是登录页"
    else:
        return "Hello World"

Web服务器

import socket
import mini_frame

class WSGIServer(object):

	def service_client(self, new_socket):
	    # 接受浏览器发送过来的请求
	    # get / http/1.1
	    request = new_socket.recv(1024).decode("utf-8")
	    req_lines = request.splitlines()
	    print("")
	    print(">" * 20)
	    print(req_lines)
	    ret = re.match(r"[^/]+(/[^ ]*)", req_lines[0])
	    file_name = ret.group(1)
		env = dict()
        env["PATH_INFO"] = file_name
        body = self.application(env, self.set_response_header)
        header = "HTTP/1.1 %s\r\n" % self.status
        for temp in self.headers:
            header += "%s:%s\r\n" % (temp[0], temp[1])
        header += "\r\n"
        response = header + body
        new_socket.send(response.encode("utf-8"))

        new_socket.close()

    def set_response_header(self, starts, headers):
        self.status = starts
        self.headers = [("Server","mini_web v8.8")]
        self.headers += headers

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
    # 绑定
    tcp_server_socket.bind(("",7890))
    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:
        #   等待新的客户端连接
        new_socket, client_addr = tcp_server_socket.accept()
        # 为这个客户端服务
		wsgi_server = WSGIServer()
	    wsgi_server.service_client(new_socket)
	
	 #  关闭监听套接字
    tcp_server_socket.close()


if __name__ == '__main__':
    main()