python:記一次簡單的模擬flas

最近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源碼