• WSGI


    1. 什么是WSGI

    Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器Web应用程序框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。

    2. 发展历史

    1989年

    特点:

    server只能返回静态文件,例如html,css,image等静态文件

    过程:服务器收到request请求,知道要获取index.html,服务器从硬盘中读取index.html的内容, 将读取的内容放在body中返回。

    1991年

    需求:想让服务器返回html form表单

    特点:

     

    1997年

    出现了公共的网管接口:CGI

    目的是为了设置一组规范,命名一些环境变量,以及声明它们的用途。

    公共网关接口(Common Gateway Interface,CGI)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能。
    CGI 应用程序能与浏览器进行交互,还可通过数据API与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为HTML文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。几乎所有服务器都支持CGI,可用任何语言编写CGI,
    包括流行的C、C ++、Java、VB 和Delphi 等。CGI分为标准CGI和间接CGI两种。标准CGI使用命令行参数或环境变量表示服务器的详细请求,服务器与浏览器通信采用标准输入输出方式。间接CGI又称缓冲CGI,在CGI程序和CGI接口之间插入一个缓冲程序,
    缓冲程序与CGI接口间用标准输入输出进行通信

     规定了下图的内容

    2003年

    python为了进一步的执行cgi的标准,因此规定了标准化脚本,任何从web服务器调用脚本,都必须拥有类似于nerdy的函数。函数接受两个变量,env是一个dict字典,用来存储cgi规定的变量。foo是一个特殊参数(函数),只需要已特定的方式调用第二个参数即可。

    foo函数的两个参数
    1. http_status --- response的status
    2. http_headers_list --- response的headers

    nerdy函数返回值,就是response的body部分

    3. 自己实现WSGI的转发

    实现WSGI转发,需要实现wsgi服务器(类似于gunicorn)和application(类似于flask/django)

    3.1 实现wsgi服务器

    # encoding:utf-8
    # @Time : 2021/6/27 6:20 下午
    # @Author : yan
    # @Content: 模仿wsgi服务器, 类似于gunicorn
    
    from wsgiref.simple_server import make_server
    from web服务器的实现原理.WSGI协议转发.application import application
    
    # 类似于gunicorn配置文件的bind, 启动 gunicron -c gun.py application:applicaton
    httpd = make_server('127.0.0.1', 9000, application)
    print("Serving HTTP on port 9000...")
    # 开始监听HTTP请求:
    httpd.serve_forever()

    3.2实现web应用程序

    # encoding:utf-8
    # @Time : 2021/6/27 6:20 下午
    # @Author : yan
    # @Content: 模仿flask应用
    
    def application(environ, start_response):
        """
        这个函数flask或者django已经封装好了,里面的request对象,会将environ的参数进行绑定。
        """
        # environ {'PATH': '/Users/yanyanzhang/opt/anaconda3/bin:/Users/yanyanzhang/opt/anaconda3/condabin:/usr/local/sbin:/usr/local/bin:/Library/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/usr/local/go/bin:/usr/local/mysql/bin:/usr/local/go/bin:/Users/yanyanzhang/goProject', 'CONDA_DEFAULT_ENV': 'base', 'CONDA_EXE': '/Users/yanyanzhang/opt/anaconda3/bin/conda', 'JAVA_HOME': '/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home', 'CONDA_PYTHON_EXE': '/Users/yanyanzhang/opt/anaconda3/bin/python', 'LANG': 'en_US.UTF-8', 'CONDA_PREFIX': '/Users/yanyanzhang/opt/anaconda3', '_CE_M': '', 'LOGNAME': 'yanyanzhang', 'XPC_SERVICE_NAME': 'com.jetbrains.pycharm.3452', 'PWD': '/Users/yanyanzhang/leifeng/leifeng-python-knowledge/web服务器的实现原理/WSGI协议转发', 'PYCHARM_HOSTED': '1', 'CONDA_SHLVL': '1', 'PYCHARM_DISPLAY_PORT': '63342', 'PYTHONPATH': '/Users/yanyanzhang/leifeng/leifeng-python-knowledge:/Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm_matplotlib_backend:/Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm_display', 'SHELL': '/bin/bash', 'PYTHONIOENCODING': 'UTF-8', 'HOMEBREW_BOTTLE_DOMAIN': 'https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles', 'GOPATH': '/Users/yanyanzhang/goProject', 'USER': 'yanyanzhang', 'GOROOT': '/usr/local/go', 'TMPDIR': '/var/folders/93/gyvmf3qj2w3ft0yj47rtpnmr0000gn/T/', 'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.tNGhZcQUd3/Listeners', 'GOBIN': '/usr/local/go/bin', '_CE_CONDA': '', 'XPC_FLAGS': '0x0', 'PYTHONUNBUFFERED': '1', 'LC_ALL': 'en_US.UTF-8', '__CF_USER_TEXT_ENCODING': '0x1F5:0x19:0x34', 'Apple_PubSub_Socket_Render': '/private/tmp/com.apple.launchd.hD6UGiLN7J/Render', 'CONDA_PROMPT_MODIFIER': '(base) ', 'HOME': '/Users/yanyanzhang', '__PYVENV_LAUNCHER__': '/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7', 'SERVER_NAME': '1.0.0.127.in-addr.arpa', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '9000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:9000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_SEC_CH_UA': '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"', 'HTTP_SEC_CH_UA_MOBILE': '?0', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'HTTP_SEC_FETCH_SITE': 'none', 'HTTP_SEC_FETCH_MODE': 'navigate', 'HTTP_SEC_FETCH_USER': '?1', 'HTTP_SEC_FETCH_DEST': 'document', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_COOKIE': 'csrftoken=yuqdKIvcb4n1XDwwM8APng4df84hlLQ1sZead7YBshaS1fITeUI6awsUTEWD1q9L', 'wsgi.input': <_io.BufferedReader name=5>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}
        print("environ", environ)
        # start response <bound method BaseHandler.start_response of <wsgiref.simple_server.ServerHandler object at 0x10bce5f60>>
        print("start response", start_response)
        response_body = '<h1>Hello, web!</h1>'
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [response_body.encode("utf-8")]

    浏览器请求结果

    4. werkzeug文档

    Werkzeug 并不是 一个框架,它是一个 WSGI 工具集的库,你可以通过它来创建你自己的框架或 Web 应用。

    pip3 install Werkzeug

    pip3 install Jinja2

    3.2 中的 application


    def application(environ, start_response):
    print("start response", start_response) response_body = '<h1>Hello, web!</h1>'
       # start_response是WSGI传递进来的一个方法,可以和环境进行通信,环境包含了进来的所有信息,start_response表明收到了一个响应。
      start_response('200 OK', [('Content-Type', 'text/html')]) return [response_body.encode("utf-8")]

    # TODO

  • 相关阅读:
    产生财务计帐周期
    判断指定年份是否为闰年
    判断是否是闰年
    Regex quick reference
    组合外键(FOREIGN KEY)
    多列组合为主键(PRIMARY KEY)
    获取字符串开始的地址(案例)
    获取字符串结尾的电话号码(案例)
    ms sql server line feed
    如何产生连续时间?(案例)
  • 原文地址:https://www.cnblogs.com/meloncodezhang/p/14905242.html
Copyright © 2020-2023  润新知