
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中,因为如果直接返回字符串,则会迭代字符串中的每一个字符,会降低效率。
查看environpython中有一个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='处理GET请求' 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请求:
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 = """处理POST请求Name: %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()
Hobbies: %s
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
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)