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

WSGI+WEBOB+ROUTES学习笔记(一),第1张

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 applicationweb 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:UserssonglinfengAppDataRoaming
COMMONPROGRAMFILES: C:Program FilesCommon Files
COMMonPROGRAMFILES(X86): C:Program Files (x86)Common Files
COMMONPROGRAMW6432: C:Program FilesCommon Files
COMPUTERNAME: songlinfeng00
COMSPEC: C:windowssystem32cmd.exe
CONTENT_LENGTH: 
CONTENT_TYPE: text/plain
DRIVERdata: C:WindowsSystem32DriversDriverData
FPS_BROWSER_APP_PROFILE_STRING: Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING: Default
GATEWAY_INTERFACE: CGI/1.1
HOMEDRIVE: C:
HOMEPATH: Userssonglinfeng
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:UserssonglinfengDesktop
LOCALAPPdata: C:UserssonglinfengAppDataLocal
LOGONSERVER: \JTZZDNS01
NUMBER_OF_PROCESSORS: 8
ONEDRIVE: C:UserssonglinfengOneDrive
OS: Windows_NT
PATH: D:VMware Playerbin;C:windowssystem32;C:windows;C:windowsSystem32Wbem;C:windowsSystem32WindowsPowerShellv1.0;C:windowsSystem32OpenSSH;D:MinGWbin;D:Gitcmd;D:pythonscripts;D:python;C:UserssonglinfengAppDataLocalMicrosoftWindowsApps;;D:Microsoft VS Codebin
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 FilesWindowsPowerShellModules;C:windowssystem32WindowsPowerShellv1.0Modules
PUBLIC: C:UsersPublic
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:UsersSONGLI~1AppDataLocalTemp
TMP: C:UsersSONGLI~1AppDataLocalTemp
UATdata: C:WindowsCCMUATDataD9F8C395-CAB8-491d-B8AC-179A1FE1BE77
USERDNSDOMAIN: HOME.LANGCHAO.COM
USERDOMAIN: HOME
USERDOMAIN_ROAMINGPROFILE: HOME
USERNAME: songlinfeng
USERPROFILE: C:Userssonglinfeng
WINDIR: C:windows
ZES_ENABLE_SYSMAN: 1
wsgi.errors: <_io.TextIOWrapper name='' mode='w' encoding='utf-8'>
wsgi.file_wrapper: 
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 = """


   
   

Name: %s
Hobbies: %s

""" 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

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zaji/5707889.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-17
下一篇2022-12-17

发表评论

登录后才能评论

评论列表(0条)

    保存