wsgi与web应用的骨架

1、WSGI是什么

wsgi:Web Server Gateway Interface,是一种协议。用于定义Server与app之间的交互方式。
wsgi把应用分成了3个组件:
1. web server:
主要实现:
1.socket通讯服务器端,监听端口
2.接收、解析http报文
3.读取服务器端的html文档,把读取的html文档response回浏览器,这是静态服务器,如nginx、Apache
4.调用app,返回app执行结果给浏览器。这是动态服务器,如Tomcat。
2. web app
1.一个函数或类的方法
2.遵循固定格式的入口函数_call_()、入参(environ,start_response)、返回值
3. 中间件
1.server与app中间的程序(所以叫中间件)
2.路由
3.流量控制等
在这里插入图片描述ps:
wsgi对web应用的划分太精辟了,对WebServer的理解、应用、url转应用调用等场景的理解豁然开朗。
以前只知道Tomcat,按这个概念套用,也更清楚了。

2、举个例子加深理解

# coding=utf-8

import socket
import sys

class WSGIServer:
    def __init__(self):
        self.listener=socket.socket()
        self.listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.listener.bind(('0.0.0.0',8080))
        self.listener.listen(1)
        print('Serving HTTP 0.0.0.0 port 8080')
        self.app=None
        self.headers_set=None


    def set_app(self,application):
        self.app=application

    ##start_response是服务器提供的函数,供app调用
    def start_response(self,status,headers):
        self.headers_set=[status,headers]

    def serve_forever(self):
        while True:
            listener=self.listener
            client_connection,client_address=listener.accept()

            ##socket服务器端,接收数据,是http协议的报文
            request=client_connection.recv(1024)
            print(f'request we received:{request}')

            method,path,_=request.split(b' ',2)

            environ = {
    
    
                'wsgi.version': (1, 0),
                'wsgi.url_scheme': 'http',
                'wsgi.input': request,
                'wsgi.errors': sys.stderr,
                'wsgi.multithread': False,
                'wsgi.multiprocess': False,
                'wsgi.run_once': False,
                'REQUEST_METHOD': method.decode('utf-8'),
                'PATH_INFO': path.decode('utf-8'),
                'SERVER_NAME': '127.0.0.1',
                'SERVER_PORT': '8080',
             }

            ##server调用app,传入environ(接收到的http报文)和start_response函数
            ##app内执行传入的start_response函数,并返回结果http内容
            app_result=self.app(environ,self.start_response)


            ##response和app返回的内容构成整个响应的html
            response_status,response_headers=self.headers_set
            response=f'HTTP/1.1 {response_status}\r\n'
            for header in response_headers:
                response+=f'{header[0]}:{header[1]}\r\n'
            response+='\r\n'
            response=response.encode('utf-8')

            for data in app_result:
                response+=data

            ##通过网络通讯,返回完整的响应http
            client_connection.sendall(response)
            client_connection.close()
            print('!!!!!!!!one request responsed!!!!!!!!')


if __name__=='__main__':
    if len(sys.argv)<2:
        sys.exit('argv error')

    app_path=sys.argv[1]
    module,app=app_path.split(':')
    module=__import__(module)
    app=getattr(module,app)
    server=WSGIServer()
    server.set_app(app)
    server.serve_forever()

在上边的程序了里:

  1. init(self):定义socket通讯的服务器端,用来监听端口、接收数据、返回数据。
  2. serve_forever(self):调用app,生成相应的http报文,在通过socket返回。
  3. 浏览器:接收服务器返回的http报文,然后渲染展示。

3、看看http请求和相应报文

对程序的部分内容加深理解。

3.1 请求报文

包括:请求的方法、url、客户端程序类型等。
浏览器自动生成并发送的。

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

3.2 响应报文

注意遵守固定格式,响应头包括协议版本、响应编号、响应结果,
然后,与实际内容中间间隔一个空行。

HTTP/1.1 200 OK

Hello, World!

猜你喜欢

转载自blog.csdn.net/heroicpoem/article/details/104419903
今日推荐