精华内容
参与话题
问答
  • WSGI

    2020-09-13 23:12:12
    WSGI 什么是WSGI WSGI:全称是Web Server Gateway Interface,WSGI协议是描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web ...

    WSGI

    什么是WSGI

    WSGI:全称是Web Server Gateway Interface,WSGI协议是描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Torando,Flask,Django等。

    WSGI协议主要包括server、application和middlewares部分

    WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,可以选择任意的server和application组合实现自己的web应用。

    例如:uWSGI和Gunicorn都是实现了WSGI server协议的服务器;Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。

    WSGI server

    WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;

    WSGI application

    WSGI application接收由server转发的request,处理请求,并将处理结果返回给server。

    中间件

    application中可以包括多个中间件(middlewares),这些中间件需要同时实现server与application,因此可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。

    实现简单的WSGI

    实现WSGI协议必须要有wsgi server和application,一般application需要我们自己实现。
    有很多符合WSGI规范的服务器,这里使用python内置的wsgiref模块,它是用纯Python编写的WSGI服务器的参考实现。

    application是一个函数

    from wsgiref.simple_server import make_server
    
    
    # 创建app,接收两个参数environ,start_response
    # 第一个参数environ就是一个字典,里面存着环境变量,里面的内容和CGI的环境变量基本一致。 
    # 第二个参数start_response是一个函数,用于输出HTTP的响应头,start_response一般有两个参数:第一个参数是就是状态码,比如200 OK,302 Found之类的。第二个参数则是HTTP首部的其他信息,是一个多个元组构成的list。每个首部字段,都放置到一个元组之中。
    # 最终的返回值,就是HTTP响应的实体部分了,必须是一个可迭代对象(python3中需要编码为bytes类型)。
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ['<h1>Hello, web!</h1>'.encode("utf-8")]
    
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    httpd = make_server('127.0.0.1', 8890, application)
    # 开始监听HTTP请求:
    httpd.serve_forever()
    

    在这里插入图片描述

    application是一个对象

    from wsgiref.simple_server import make_server
    
    # 可调用对象是一个 Application对象
    class Application(object):
        def __init__(self):
            pass
    
        def __call__(self, environ, start_response):
            status = '200 OK'
            response_headers = [('Content-type', 'text/plain')]
            start_response(status, response_headers)
            return ["Hello world!\n".encode("utf-8")]
    
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    app = Application()
    httpd = make_server('127.0.0.1', 8890, app)
    # 开始监听HTTP请求:
    httpd.serve_forever()
    

    实现简单的路由

    import re
    from wsgiref.simple_server import make_server
    
    
    def application(environ, start_response):
        method = environ["REQUEST_METHOD"].lower()
        path = environ["PATH_INFO"].lstrip("/")
        if path == "favicon.ico":
            start_response('200 OK', [('Content-Type', 'text/html')])
            return ["".encode("utf-8")]
        res = None
        for url, controller in urls:
            if re.match(url, path):
                if isinstance(controller, type) and hasattr(controller, method):
                    res = getattr(controller(), method)()
                else:
                    start_response('502 Bad Gateway', [('Content-Type', 'text/html')])
                    return ["Invalid method".encode("utf-8")]
    
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [res.encode("utf-8")]
    
    
    class HelloController(object):
        def get(self, *args, **kwargs):
            return "Hello world"
    
        def post(self, *args, **kwargs):
            pass
    
    
    urls = [
        (r"hello", HelloController)
    ]
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    httpd = make_server('127.0.0.1', 8890, application)
    # 开始监听HTTP请求:
    httpd.serve_forever()
    

    在这里插入图片描述

    支持HTTPS的web server

    wsgiref不支持https,可以借助第三方模块gevent和eventlet都可以完成:

    from eventlet import wsgi
    import eventlet
    
    wsgi.server(eventlet.wrap_ssl(eventlet.listen(('', 8443)),
                                  certfile='cert.crt',
                                  keyfile='private.key',
                                  server_side=True),
                application)
    

    其中certfile和keyfile是服务端的证书和私钥文件,可用openssl命令生成自签名的证书和私钥。
    虽然使用了一个第三方库,启动server的代码与wsgiref模块不太相同,但是之前编写的application回调函数可以直接在这里使用。也就是说我们的回调是与具体server无关的,更换另一个支持wsgi协议的server,只是在启动的代码做些修改,而我们所关心的业务逻辑则丝毫无需改动。

    https://zhuanlan.zhihu.com/p/25939345

    展开全文
  • wsgi

    2019-10-09 01:23:00
    wsgi,通用网关接口。相当于在app与web服务(socket服务端)之间建立统一连接的规范。 真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求...

    wsgi,通用网关接口。相当于在app与web服务(socket服务端)之间建立统一连接的规范。

    真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,有支持它的服务器才能被开发者使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

    WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。

    python标准库提供的独立WSGI服务器称为wsgiref。

    # -- coding: utf-8 --
    
    _author__ = "HuaQiang Yan"
    
    
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b'<h1>Hello, web!</h1>']
    
    # -- coding: utf-8 --
    
    # 从wsgiref模块导入:
    from wsgiref.simple_server import make_server
    # 导入我们自己编写的application函数:
    from wsgi import application
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    httpd = make_server('', 8000, application)
    print('Serving HTTP on port 8000...')
    # 开始监听HTTP请求:
    httpd.serve_forever()
    

     

    转载于:https://www.cnblogs.com/yanhuaqiang/p/11348903.html

    展开全文

空空如也

1 2 3 4 5 ... 20
收藏数 9,451
精华内容 3,780
关键字:

wsgi