WSGI
介绍
WSGI (Web Server Gateway Interface)不是服务器,python模块,框架,API或任何类型的软件。 它只是服务器和应用程序通信的接口规范。 服务器和应用程序接口端都在PEP 3333中指定。如果将应用程序(或框架或工具包)写入WSGI规范,则它将在写入该规范的任何服务器上运行。
Application Interface
The WSGI application interface is implemented as a callable object: a function, a method, a class or an instance with an object.__call__() method. That callable must:
- accept two positional parameters:
- A dictionary containing CGI like variables; and
- a callback function that will be used by the application to send HTTP status code/message and HTTP headers to the server.
- return the response body to the server as strings wrapped in an iterable.
1 #! /usr/bin/env python 2 3 # Python's bundled WSGI server 4 from wsgiref.simple_server import make_server 5 6 def application (environ, start_response): 7 8 # Sorting and stringifying the environment key, value pairs 9 response_body = [ 10 '%s: %s' % (key, value) for key, value in sorted(environ.items()) 11 ] 12 response_body = '\n'.join(response_body) 13 14 status = '200 OK' 15 response_headers = [ 16 ('Content-Type', 'text/plain'), 17 ('Content-Length', str(len(response_body))) 18 ] 19 start_response(status, response_headers) 20 21 return [response_body] 22 23 # Instantiate the server 24 httpd = make_server ( 25 'localhost', # The host name 26 8051, # A port number where to wait for the request 27 application # The application object name, in this case a function 28 ) 29 30 # Wait for a single request, serve it and quit 31 httpd.handle_request()
解析请求 - GET
1 #!/usr/bin/env python 2 3 from wsgiref.simple_server import make_server 4 from cgi import parse_qs, escape 5 6 html = """ 7 <html> 8 <body> 9 <form method="get" action=""> 10 <p> 11 Age: <input type="text" name="age" value="%(age)s"> 12 </p> 13 <p> 14 Hobbies: 15 <input 16 name="hobbies" type="checkbox" value="software" 17 %(checked-software)s 18 > Software 19 <input 20 name="hobbies" type="checkbox" value="tunning" 21 %(checked-tunning)s 22 > Auto Tunning 23 </p> 24 <p> 25 <input type="submit" value="Submit"> 26 </p> 27 </form> 28 <p> 29 Age: %(age)s<br> 30 Hobbies: %(hobbies)s 31 </p> 32 </body> 33 </html> 34 """ 35 36 def application (environ, start_response): 37 38 # Returns a dictionary in which the values are lists 39 d = parse_qs(environ['QUERY_STRING']) 40 41 # As there can be more than one value for a variable then 42 # a list is provided as a default value. 43 age = d.get('age', [''])[0] # Returns the first age value 44 hobbies = d.get('hobbies', []) # Returns a list of hobbies 45 46 # Always escape user input to avoid script injection 47 age = escape(age) 48 hobbies = [escape(hobby) for hobby in hobbies] 49 50 response_body = html % { # Fill the above html template in 51 'checked-software': ('', 'checked')['software' in hobbies], 52 'checked-tunning': ('', 'checked')['tunning' in hobbies], 53 'age': age or 'Empty', 54 'hobbies': ', '.join(hobbies or ['No Hobbies?']) 55 } 56 57 status = '200 OK' 58 59 # Now content type is text/html 60 response_headers = [ 61 ('Content-Type', 'text/html'), 62 ('Content-Length', str(len(response_body))) 63 ] 64 65 start_response(status, response_headers) 66 return [response_body] 67 68 httpd = make_server('localhost', 8051, application) 69 70 # Now it is serve_forever() in instead of handle_request() 71 httpd.serve_forever()
解析请求 - POST
1 #!/usr/bin/env python 2 3 from wsgiref.simple_server import make_server 4 from cgi import parse_qs, escape 5 6 html = """ 7 <html> 8 <body> 9 <form method="post" action=""> 10 <p> 11 Age: <input type="text" name="age" value="%(age)s"> 12 </p> 13 <p> 14 Hobbies: 15 <input 16 name="hobbies" type="checkbox" value="software" 17 %(checked-software)s 18 > Software 19 <input 20 name="hobbies" type="checkbox" value="tunning" 21 %(checked-tunning)s 22 > Auto Tunning 23 </p> 24 <p> 25 <input type="submit" value="Submit"> 26 </p> 27 </form> 28 <p> 29 Age: %(age)s<br> 30 Hobbies: %(hobbies)s 31 </p> 32 </body> 33 </html> 34 """ 35 36 def application(environ, start_response): 37 38 # the environment variable CONTENT_LENGTH may be empty or missing 39 try: 40 request_body_size = int(environ.get('CONTENT_LENGTH', 0)) 41 except (ValueError): 42 request_body_size = 0 43 44 # When the method is POST the variable will be sent 45 # in the HTTP request body which is passed by the WSGI server 46 # in the file like wsgi.input environment variable. 47 request_body = environ['wsgi.input'].read(request_body_size) 48 d = parse_qs(request_body) 49 50 age = d.get('age', [''])[0] # Returns the first age value. 51 hobbies = d.get('hobbies', []) # Returns a list of hobbies. 52 53 # Always escape user input to avoid script injection 54 age = escape(age) 55 hobbies = [escape(hobby) for hobby in hobbies] 56 57 response_body = html % { # Fill the above html template in 58 'checked-software': ('', 'checked')['software' in hobbies], 59 'checked-tunning': ('', 'checked')['tunning' in hobbies], 60 'age': age or 'Empty', 61 'hobbies': ', '.join(hobbies or ['No Hobbies?']) 62 } 63 64 status = '200 OK' 65 66 response_headers = [ 67 ('Content-Type', 'text/html'), 68 ('Content-Length', str(len(response_body))) 69 ] 70 71 start_response(status, response_headers) 72 return [response_body] 73 74 httpd = make_server('localhost', 8051, application) 75 httpd.serve_forever()