您的位置:首页 > 编程语言 > Python开发

Python Web Server Gateway Interface(WSGI)

2017-12-14 16:06 344 查看
learned by Let’s Build A Web Server. Part 2.

run your Web server with multiple Web frameworks without making code changes either to the Web server or to the Web frameworks

import socket,sys
from io import StringIO
class WSGIServer(object):
#ipv4
address_family = socket.AF_INET
#tcp
socket_type = socket.SOCK_STREAM
request_queue_size = 1
recv_size = 1024

def __init__(self,server_address):
#create a listening socket
self.listen_socket = listen_socket = socket.socket(self.address_family,self.socket_type)
#allow to reuse the same port after releasing
listen_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#bind
listen_socket.bind(server_address)
#activate
listen_socket.listen(self.request_queue_size)
#get listening host full name and port
host,port = self.listen_socket.getsockname()[:2]
self.server_name = socket.getfqdn(host)
self.server_port = port
self.headers_set = []

def set_app(self,application):
self.application = application

def serve_forever(self):
listen_socket = self.listen_socket
while True:
#get new client connection
self.client_connection,client_address = listen_socket.accept()
#handle the request and then close it ro listen the next request
self.handle_one_request()

def handle_one_request(self):
self.request_data = request_data = self.client_connection.recv(self.recv_size)
#print format request data
print(''.join('< {line}\n'.format(line = line) for line in request_data.splitlines()))

#parse the request info
self.parse_request(request_data)
#construct the environment dictionary depend on the request data
env = self.get_environ()
#call the application to construct the response data body
result = self.application(env,self.start_response)
#send the response message to the client
self.finish_response(result)

def parse_request(self,text):
request_line = text.splitlines()[0].rstrip('\r\n')
#break down the request line and get the components needed
self.request_method,self.path,self,request_version = request_line.split()

def get_env(self):
env = {}
#wsgi variables
env['wsgi.version'] = (1,0)
env['wsgi.url_scheme'] = 'http'
env['wsgi.input'] = StringIO.StringIO(self.request_data)
env['wsgi.errors'] = sys.stderr
env['wsgi.multithread'] = False
env['wsgi.multiprocess'] = False
env['wsgi.run_once'] = False
#CGI variables
env['REQUEST_METHOD'] = self.request_method
env['PATH_INFO'] = self.path
env['SERVER_NAME'] = self.server_name
enc['SERVER_PORT'] = self.server_port
return env

def start_response(self,status,response_headers,exc_info=None):
server_headers = [
('Data','Thu,14 Dec 2017 14:55:00 GMT'),
('Server','WSGIServer 0.2'),
]
self.headers_set = [status,response_headers + server_headers]

def finish_response(self,result):
try:
status,response_headers = self.headers_set
response = 'HTTP/1.1 {status}\r\n'.format(status = status)

for header in response_headers:
response += '{0}: {1}\r\n'.format(*header)
response += '\r\n'

for data in result:
response += data

print(''.join('> {line}\n'.format(line = line) for line in response.splitlines()))
self.client_connection.sendall(response)
finally:
self.client_connection.close()

SERVER_ADDRESS = (HOST,PORT) = '',8888

def make_server(server_address,application):
server = WSGIServer(server_address)
server.set_app(application)
return server

if __name__ == '__main__':
if len(sys.argv) < 2:
sys.exit('please provide a WSGI application object as module:callable')
app_path = sys.argv[1]
module,application = app_path.split(':')
module = __import__(module)
application = getattr(module,application)
httpd = make_server(SERVER_ADDRESS,application)
print('WSGIServer:Serving HTTP on port {port}...\n'.format(port=PORT))
httpd.serve_forever()


4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python WSGI