WSGI+WEBOB+ROUTES学习笔记(一)

WSGI和WEBOB和ROUTES主要用于组合起来处理web发送过来的请求并将响应返回给web端,本篇主要来记录以下wsgi模块的作用。

什么是WSGI

在接收到HTTP的请求时,我们不需要关心是怎样接收到的,我们需要关心的是怎样处理传送来的请求,并将响应返回给web端。WSGI的作用就在这里,它主要应用于web server和web application之间。
Web Server和Web application都实现了WSGI规范,然后各司其职:

  • web server:接收来自客户端的HTTP请求,然后将请求交给web application
  • web application:根据请求来调用响应的处理逻辑,生成response,通过web server把response发送给客户端

这个web application必须是一个可调用对象(类,方法,函数或实现__call__方法的类实例),这个callable对象需要满足下面两个条件:

  • 包含两个参数

    • environ:是一个字典,里面包含了WSGI的基本信息和HTTP协议里的请求行,请求头,请求数据等信息
    • start_response:是一个回调函数,web application通过这个函数将HTTP status code和headers发送给Web Server
  • 一个返回值:返回值主要是response_body,最好放在list中,因为如果直接返回字符串,则会迭代字符串中的每一个字符,会降低效率。

在这里插入图片描述

查看environ

python中有一个WSGI server,我们可以直接使用

# WSGI server in Python
from wsgiref.simple_server import make_server


def application(environ, start_response):
    # 遍历并排序environ中的键值对
    response_body = ['%s: %s' % (key, value)
                     for key, value in sorted(environ.items())]
    response_body = '\n'.join(response_body)
    #定义响应行
    status = '200 OK'
    #定义响应头
    response_headers = [('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(response_body)))]
    #将响应行,响应头返回给web server
    start_response(status, response_headers)

    return [response_body.encode('utf-8')]#注意转换的字节流


# Instantiate the WSGI server.
# It will receive the request, pass it to the application
# and send the application's response to the client
httpd = make_server(
    'localhost',  # The host name.
    8080,  # A port number where to wait for the request.
    application  # Our application object name, in this case a function.
)

# Wait for a single request, serve it and quit.
#httpd.handle_request()

# Keep the server always alive with serve_forever()
httpd.serve_forever()

web端返回结果如下:

ALLUSERSPROFILE: C:\ProgramData
APPDATA: C:\Users\songlinfeng\AppData\Roaming
COMMONPROGRAMFILES: C:\Program Files\Common Files
COMMONPROGRAMFILES(X86): C:\Program Files (x86)\Common Files
COMMONPROGRAMW6432: C:\Program Files\Common Files
COMPUTERNAME: songlinfeng00
COMSPEC: C:\windows\system32\cmd.exe
CONTENT_LENGTH: 
CONTENT_TYPE: text/plain
DRIVERDATA: C:\Windows\System32\Drivers\DriverData
FPS_BROWSER_APP_PROFILE_STRING: Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING: Default
GATEWAY_INTERFACE: CGI/1.1
HOMEDRIVE: C:
HOMEPATH: \Users\songlinfeng
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_ACCEPT_ENCODING: gzip, deflate, br
HTTP_ACCEPT_LANGUAGE: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP_CACHE_CONTROL: max-age=0
HTTP_CONNECTION: keep-alive
HTTP_HOST: 127.0.0.1:8080
HTTP_SEC_CH_UA: " Not;A Brand";v="99", "Microsoft Edge";v="97", "Chromium";v="97"
HTTP_SEC_CH_UA_MOBILE: ?0
HTTP_SEC_CH_UA_PLATFORM: "Windows"
HTTP_SEC_FETCH_DEST: document
HTTP_SEC_FETCH_MODE: navigate
HTTP_SEC_FETCH_SITE: none
HTTP_SEC_FETCH_USER: ?1
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.62
IDEA_INITIAL_DIRECTORY: C:\Users\songlinfeng\Desktop
LOCALAPPDATA: C:\Users\songlinfeng\AppData\Local
LOGONSERVER: \\JTZZDNS01
NUMBER_OF_PROCESSORS: 8
ONEDRIVE: C:\Users\songlinfeng\OneDrive
OS: Windows_NT
PATH: D:\VMware Player\bin\;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\windows\System32\OpenSSH\;D:\MinGW\bin;D:\Git\cmd;D:\python\Scripts\;D:\python\;C:\Users\songlinfeng\AppData\Local\Microsoft\WindowsApps;;D:\Microsoft VS Code\bin
PATHEXT: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PATH_INFO: /
PROCESSOR_ARCHITECTURE: AMD64
PROCESSOR_IDENTIFIER: Intel64 Family 6 Model 140 Stepping 1, GenuineIntel
PROCESSOR_LEVEL: 6
PROCESSOR_REVISION: 8c01
PROGRAMDATA: C:\ProgramData
PROGRAMFILES: C:\Program Files
PROGRAMFILES(X86): C:\Program Files (x86)
PROGRAMW6432: C:\Program Files
PSMODULEPATH: C:\Program Files\WindowsPowerShell\Modules;C:\windows\system32\WindowsPowerShell\v1.0\Modules
PUBLIC: C:\Users\Public
PYCHARM_HOSTED: 1
PYTHONIOENCODING: UTF-8
PYTHONPATH: D:\python鍩虹\pythonProject1
PYTHONUNBUFFERED: 1
QUERY_STRING: 
REMOTE_ADDR: 127.0.0.1
REMOTE_HOST: 
REQUEST_METHOD: GET
SCRIPT_NAME: 
SERVER_NAME: songlinfeng00.home.langchao.com
SERVER_PORT: 8080
SERVER_PROTOCOL: HTTP/1.1
SERVER_SOFTWARE: WSGIServer/0.2
SESSIONNAME: Console
SYSTEMDRIVE: C:
SYSTEMROOT: C:\windows
TEMP: C:\Users\SONGLI~1\AppData\Local\Temp
TMP: C:\Users\SONGLI~1\AppData\Local\Temp
UATDATA: C:\Windows\CCM\UATData\D9F8C395-CAB8-491d-B8AC-179A1FE1BE77
USERDNSDOMAIN: HOME.LANGCHAO.COM
USERDOMAIN: HOME
USERDOMAIN_ROAMINGPROFILE: HOME
USERNAME: songlinfeng
USERPROFILE: C:\Users\songlinfeng
WINDIR: C:\windows
ZES_ENABLE_SYSMAN: 1
wsgi.errors: <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>
wsgi.file_wrapper: <class 'wsgiref.util.FileWrapper'>
wsgi.input: <_io.BufferedReader name=944>
wsgi.multiprocess: False
wsgi.multithread: False
wsgi.run_once: False
wsgi.url_scheme: http
wsgi.version: (1

处理GET请求

当我们执行一个如下的GET请求:
http://127.0.0.1:8080/?name=wilber&hobbies=software
QUERY_STRING(URL中”?“之后的部分)和REQUEST_METHOD这些信息会包含在environ参数中,可以使用cgi模块中的parse_qs将一个由QUERY_STRING生成的字典,方便我们取出请求的变量信息。同时,为了避免客户端的输入可能存在的脚本注入,可以使用cgi模块中的escape函数对输入进行一次过滤。

from wsgiref.simple_server import make_server
from cgi import parse_qs, escape

html = """
<html>
<body>
   <form method="get" action="/">
      <p>
         Name: <input type="text" name="name">
         </p>
      <p>
         Hobbies:
         <input name="hobbies" type="checkbox" value="running"> running
         <input name="hobbies" type="checkbox" value="swimming"> swimming
         <input name="hobbies" type="checkbox" value="reading"> reading
         </p>
      <p>
         <input type="submit" value="Submit">
         </p>
      </form>
   <p>
      Name: %s<br>
      Hobbies: %s
      </p>
   </body>
</html>"""


def application(environ, start_response):
    print
    ("QUERY_STRING: %s" % environ['QUERY_STRING'])
    print
    ("REQUEST_METHOD: %s" % environ['REQUEST_METHOD'])

    # Returns a dictionary containing lists as values.
    d = parse_qs(environ['QUERY_STRING'])

    # In this idiom you must issue a list containing a default value.
    name = d.get('name', [''])[0]  # Returns the first name value.
    hobbies = d.get('hobbies', [])  # Returns a list of hobbies.

    # Always escape user input to avoid script injection
    name = escape(name)
    hobbies = [escape(hobby) for hobby in hobbies]

    response_body = html % (name or 'Empty',
                            ', '.join(hobbies or ['No Hobbies']))

    status = '200 OK'

    # Now content type is text/html
    response_headers = [('Content-Type', 'text/html'),
                        ('Content-Length', str(len(response_body)))]
    start_response(status, response_headers)

    return [response_body.encode('utf-8')]


httpd = make_server('localhost', 8080, application)
# Now it is serve_forever() in instead of handle_request().
# In Windows you can kill it in the Task Manager (python.exe).
# In Linux a Ctrl-C will do it.
httpd.serve_forever()

处理POST请求

POST请求的query string 不会出现在URL里面,而是包含在request body中。对于environ,request body 放在(environ[‘wsgi.input’]),environ[‘wsgi.input’]对应的是一个file object,可以通过读取文件的方式读取request body.同时,environ.get(‘CONTENT_LENGTH’,0)中存放着request body的size,我们可以根据这个值来读取适当长度的request body.

def application(environ, start_response):
    # the environment variable CONTENT_LENGTH may be empty or missing
    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except (ValueError):
        request_body_size = 0
        
    # When the method is POST the query string will be sent
    # in the HTTP request body which is passed by the WSGI server
    # in the file like wsgi.input environment variable.
    request_body = environ['wsgi.input'].read(request_body_size)
    d = parse_qs(request_body)
    
    print "wsgi.input %s" %environ['wsgi.input']
    print "request_body_size %s" %environ.get('CONTENT_LENGTH', 0)
    print "request_body %s" %request_body
    
    
    name = d.get('name', [''])[0] # Returns the first name value.
    hobbies = d.get('hobbies', []) # Returns a list of hobbies.
    
    # Always escape user input to avoid script injection
    name = escape(name)
    hobbies = [escape(hobby) for hobby in hobbies]
    
    response_body = html % (name or 'Empty',
                ', '.join(hobbies or ['No Hobbies']))
    
    status = '200 OK'
    
    response_headers = [('Content-Type', 'text/html'),
                ('Content-Length', str(len(response_body)))]
    start_response(status, response_headers)
    
    return [response_body]

参考
https://www.cnblogs.com/wilber2013/p/4763067.html

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Nginx是一款高性能的Web服务器,并且也可以作为反向代理服务器和负载均衡器使用。它的特点是占用资源少、稳定性高、并发能力强,可以处理大量的并发连接请求。 WSGIWeb Server Gateway Interface)是一种Web服务器和Python应用程序之间的通信协议。它定义了应用程序和服务器之间的接口规范,使得不同的Python框架(如Django和Flask)可以与Web服务器(如Nginx)进行通信,实现Web应用程序的部署和运行。 PHP 7.0是一种流行的开源脚本语言,常用于Web开发。它具有丰富的功能和扩展库,使得开发人员可以快速构建动态的网站和应用程序。在Nginx中,可以通过FastCGI模块来支持PHP的解析和执行。 结合这三者,我们可以使用Nginx作为Web服务器,通过WSGI协议将请求传递给Python应用程序,同时支持PHP解析和执行。具体的配置步骤如下: 1. 安装Nginx并配置虚拟主机:通过在Nginx的配置文件中添加虚拟主机,将请求定向到正确的域名或IP地址。 2. 安装和配置Python应用程序:确保Python应用程序与WSGI兼容,并安装必要的模块。可以使用Gunicorn作为WSGI容器,它可以与Nginx配合使用。 3. 配置Nginx与Python应用程序的通信:通过在Nginx的配置文件中添加代理规则,将请求传递给Python应用程序。可以使用与WSGI兼容的Gunicorn的地址。 4. 配置Nginx与PHP的通信:通过将PHP解析器与FastCGI模块结合使用,实现Nginx对PHP的支持。可以通过在Nginx的配置文件中添加相应的规则来实现。 这样,我们就可以在同一台服务器上同时支持Python和PHP应用程序。Nginx作为Web服务器和反向代理服务器,通过WSGI协议将请求传递给Python应用程序,并利用FastCGI模块支持PHP解析和执行。整个配置的目的是为了实现高性能和稳定性,以及对多种Web开发技术的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值