python:记一次简单的模拟flask和cgi服务器
最近web服务器知识,中间懒癌犯了,断了一两天后思路有点接不上来,手头上也有其他事情要做,先简单的总结下学习进度,很多重要的功能都没跑通,目前flask只是简单实现路由分显示不同的结果,cgi可以根据不同的静态资源或者py脚本文件路径显示不同的结果。目前来说文章亮点就是解耦做的还行,有一定的可扩展性
简单的仿flask实现路由分发
from wsgiref.simple_server import make_server '''' WSGI规定: 1. 应用程序需要是一个可调用的对象 2. 可调用对象接收两个参数 3.可调用对象要返回一个值,这个值是可迭代的。 具体参考附录一,pep-0333标准 ''' class SimServer(object): def __init__(self): self.url_map = {} def __call__(self, environ, start_response): status = u'200 OK' response_headers = [('Content-type', 'text/plain')] start_response(status, response_headers) data=self.dispatch_request(environ) return [data.encode('utf-8'),] def run(self, ip=None, host=None): if not ip: ip = '' if not host: host = 8080 httpd = make_server(ip, host, self) httpd.serve_forever() #路由装饰器 def route(self, rule): def decorator(f): self.url_map[rule.lstrip('/')] = f return f return decorator #路由的分发 def dispatch_request(self, request): print(request) path = request.get('PATH_INFO', '').lstrip('/') print(path) return self.url_map[path]() # 从url_map中找到对应的处理函数,并调用 #创建一个app app=SimServer() @app.route('/index') def index(): return 'hello world' @app.route('/login') def login(): return 'please login' if __name__=="__main__": app.run() if __name__=="__main__": app.run()
CGI web服务器,静态资源的转发
handler.py
import os import subprocess class BaseHandler(object): '''Parent for case handlers.''' def handle_file(self, handler, full_path): try : with open(full_path, 'rb') as reader: content = reader.read() handler.send_content(content) except IOError as msg: msg = "'{0}' cannot be read: {1}".format(full_path, msg) handler.handle_error(msg) def index_path(self, handler): return os.path.join(handler.full_path, 'index.html') def test(self, handler): assert False, 'Not implemented.' def act(self, handler): assert False, 'Not implemented.' #处理首页 class Case_directory_idnex_file(BaseHandler): def test(self, handler): return (os.path.isdir(handler.full_path) and os.path.isfile(self.index_path(handler))) def act(self, handler): self.handle_file(handler, self.index_path(handler)) #处理普通html文件 class Case_existing_file(BaseHandler): def test(self, handler): return os.path.isfile((handler.full_path)) def act(self, handler): self.handle_file(handler,handler.full_path) #处理python脚本 class Case_cgi_file(BaseHandler): def run_cgi(self, handler): print('dfs') print(handler.full_path) data=subprocess.getoutput(['python',handler.full_path]) print('data={}'.format(data)) #python3默认使用unicode,需要encode('utf-8') return handler.send_content(data.encode('utf-8')) def test(self,handler): return os.path.isfile(handler.full_path) and \ handler.full_path.endswith('.py') def act(self,handler): self.run_cgi(handler)
requestHandler.py
from http.server import BaseHTTPRequestHandler,HTTPServer import os from simpleServer.handler import * class RequestHandler(BaseHTTPRequestHandler): Cases = [Case_cgi_file(),Case_directory_idnex_file(),Case_existing_file() ,] # How to display an error. Error_Page = """\ <html> <body> <h1>Error accessing {path}</h1> <p>{msg}</p> </body> </html> """ # Classify and handle request. def do_GET(self): try: # 使用join会有问题,目前还没搞清楚+可以,join会有问题 self.full_path = os.getcwd()+self.path # Figure out how to handle it. print('cases{}'.format(self.Cases)) for case in self.Cases: if case.test(self): case.act(self) break # 处理异常 except Exception as msg: print(msg) self.handle_error(msg) # Handle unknown objects. def handle_error(self, msg): content = self.Error_Page.format(path=self.path, msg=msg) self.send_content(content.encode('utf-8'), 404) # Send actual content. def send_content(self, content, status=200): self.send_response(status) self.send_header("Content-type", "text/html") self.send_header("Content-Length", str(len(content))) self.end_headers() self.wfile.write(content) if __name__=="__main__": severAddress=('',8000) server=HTTPServer(severAddress,RequestHandler) server.serve_forever()
参考附录
1, pyton:pep-0333
2, flask作者博客文章:getting-started-with-wsgi
3, 自己写一个 wsgi 服务器运行 Django 、Tornado 等框架应用
4, 500L:a-simple-web-server
5, python wsgi简介
6, 从零开始搭建论坛(二):Web服务器网关接口
7, python的 WSGI 简介
8,本文github源码
相关推荐
bestallen 2020-08-17
JessePinkmen 2020-07-26
washing 2020-07-18
hzyuhz 2020-07-04
hzyuhz 2020-06-28
hzyuhz 2020-06-25
苦咖啡flask 2020-06-25
苦咖啡flask 2020-06-25
苦咖啡flask 2020-06-18
washing 2020-06-16
liuweiq 2020-06-14
wushaojun 2020-06-14
JessePinkmen 2020-06-14
kgshuo 2020-06-14
JessePinkmen 2020-06-14
bestallen 2020-06-13