资讯专栏INFORMATION COLUMN

python:记一次简单的模拟flask和cgi服务器

Aldous / 2274人阅读

摘要:目前来说文章亮点就是解耦做的还行,有一定的可扩展性简单的仿实现路由分发规定应用程序需要是一个可调用的对象可调用对象接收两个参数可调用对象要返回一个值,这个值是可迭代的。

最近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 = """
        
        
        

Error accessing {path}

{msg}

""" # 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源码

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44610.html

相关文章

  • 【FAILED】一次Python后端开发面试经历

    摘要:正确的思路是等概率随机只取出共个数,每个数出现的概率也是相等的随机输出把一段代码改成,并增加单元测试。代码本身很简单,即使没学过也能看懂,改后的代码如下但是对于单元测试则仅限于听过的地步,需要用到,好像也有别的模块。 在拉勾上投了十几个公司,大部分都被标记为不合适,有两个给了面试机会,其中一个自己觉得肯定不会去的,也就没有去面试,另一个经历了一轮电话面加一轮现场笔试和面试,在此记录一下...

    kohoh_ 评论0 收藏0
  • 从零开始搭建论坛(一):Web务器与Web框架

    摘要:服务器通过协议与客户端通信,因此也被称为服务器。本文标题为从零开始搭建论坛一服务器与框架本文链接为更多阅读自己动手开发网络服务器一自己动手开发网络服务器二自己动手开发网络服务器三服务器网关接口实现原理分析最佳实践指南应用浅谈框架编程简介 之前用 Django 做过一个小的站点,感觉Django太过笨重,于是就准备换一个比较轻量级的 Web 框架来玩玩。Web.py 作者已经挂掉,项目好...

    dantezhao 评论0 收藏0
  • 如何理解Nginx, WSGI, Flask之间关系

    摘要:通过查阅了些资料,总算把它们的关系理清了。在这个过程中,服务器的作用是接收请求处理请求返回响应服务器是一类特殊的服务器,其作用是主要是接收请求并返回响应。正是为了替代而出现的。三结语最后以,,之间的对话结束本文。 刚转行互联网行业,听到了许多名词:Flask、Django、WSGI、 Nginx、Apache等等,一直无法搞清楚这些开源项目之间的关系,直至看到这篇文章后感觉醍醐灌顶,以...

    魏明 评论0 收藏0
  • 在Windows平台使用IIS部署Flask网站

    摘要:在平台部署基于的网站是一件非常折腾的事情,平台下有很多选择,本文记录了部署到的主要步骤,希望对你有所帮助。下载后运行,搜索,分别安装。使用命令可以将其移除。在中你可以使用来快捷开发并部署程序,真正让你一键无忧。 在 Windows 平台部署基于 Python 的网站是一件非常折腾的事情,Linux/Unix 平台下有很多选择,本文记录了 Flask 部署到 IIS 的主要步骤,希望对你...

    2bdenny 评论0 收藏0

发表评论

0条评论

Aldous

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<