美文网首页
2018-06-11web框架编写

2018-06-11web框架编写

作者: 菩灵 | 来源:发表于2018-06-11 22:35 被阅读0次

    【web框架编写】05:14——框架:什么是web框架?为什么要有框架?
    如果支持路径过多,需要写的单独的文件也会相应增多。
    不同文件的application之间会有通用的工具。
    不再把文件对应到路径中,而是整个网站全局只有一个如果,实现路由分发。
    把“PATH_INFO”不对应到文件中,而是对应到application中的某一个部分上,由application进行调用。
    只让web服务器加载一个文件,其中定义了一个application,建立路由信息(urls列表)进行映射,如果用户访问ctime.py执行ctime,如果访问sayhello.py执行sayhello。
    目的是把多个文件压缩,只有一个入口Myweb.py,其中的application作为全局信息,能够被web服务器调用,在被调用的时候,用户请求信息放在env中,再去做映射。


    Myweb.py中的application映射

    如果使用框架,只在urls中加入映射。
    框架:不用大规模改写,只在个别地方修改。

    在web服务器程序中只提供一个py文件,里面的application映射多个py文件。


    框架

    符合WSGI协议的情况下, 文件中的application必须可以被调用(函数或者类),由于application函数中的代码不需要被改写,保持application代码不变,只修改属性,代码和行为不变,所以把它定义成一个类。
    类中被实例的对象app需要被服务器调用,
    一小时的视频看了好几遍,代码奉上:
    web框架端(启动程序):

    # coding:utf-8
    
    import time
    import sys
    # 由于此文件是启动程序,所以需要从MyWebServer文件中导入
    from MyWebServer import HTTPServer
    
    sys.path.insert(1, './')
    
    
    class Application(object):
        """框架的核心部分,也就是框架的主体程序,框架是通用的"""
        # 构造函数接收路由信息,放入对象中保存
        def __init__(self, urls):
            # 设置路由信息
            self.urls = urls
    
        # 由于HTTPServer把application当成函数,所以需要__call__方法
        def __call__(self, env, start_response):
            # 字典的索引方式区别:get方法如果不存在不会退
            # 出(不确定存在),[]方法会报异常(很确定存在)
            # 后面的“/”表示如果没传默认根路径
            path = env.get("PATH_INFO", "/")
            # 路由分发:找到对应路径的对应程序,你去执行
            for url, handler in self.urls:
                # "/ctime", show_time()
                if path == url:
                    # handler是对应路径的函数
                    # 调用__call__之后需要有返回值,
                    # 这个返回值从执行的函数中得到
                    # 一旦发现有比对值,直接返回,程序停止执行
                    return handler(env, start_response) # 把函数返回的信息直接返回
                    # 但别忘了后面的(env, start_response)两个参数
            # 应该等到都遍历之后发现没有才返回错误信息
            # 所以错误信息从此处开始404
            status = "404 Not Nound"
            headers = []
            start_response(status, headers)
            return "not found"
    
    
    def show_ctime(env, start_response):
        status = "200 OK"
        headers = [
            ("Content-Type", "text/plain")
        ]
        start_response(status, headers)
        return time.ctime()
    
    
    def say_hello(env, start_response):
        status = "200 OK"
        headers = [
            ("Conten-Type", "text/plain")
        ]
        start_response(status, headers)
        return "hello itcast"
    
    
    if __name__ == "__main__":
    
        urls = [
            ("/", show_ctime),
            ("/ctime", show_ctime),
            ("/sayhello", say_hello)
        ]
    
        app = Application(urls)
        http_server = HTTPServer(app)  # 被明确导入了就可以直接用
        http_server.bind(8080)
        http_server.start()
        # 需要使用的时候,只需要更改urls路由信息
    

    web服务器端:

    # coding:utf-8
    
    import socket
    import sys
    import re
    
    from multiprocessing import Process
    # 定义一个常量用来接收客户端发起的文件请求地址
    # 设置静态文件根目录
    HTML_ROOT_DIR = "./html"
    WSGI_PYTHON_DIR = "./wsgipython"
    
    
    class HTTPServer(object):
        def __init__(self, application):
            """构造函数,application指的是框架的app"""
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.app = application
    
        def start(self):
            self.server_socket.listen(128)
            while True:
                client_socket, client_address = self.server_socket.accept()
                print("[%s, %s]用户连接上了" % client_address)
                handle_client_process = Process(target=self.handle_client, args=(client_socket,))
                handle_client_process.start()
                client_socket.close()
    
        def start_response(self, status, headers):
            """
                     status = "200 OK"
                headers = [
                    ("Content-Type", "text/plain")
                ]
                star
                    """
            response_headers = "HTTP1.1 " + status + "\r\n"
            for header in headers:
                response_headers += "%s: %s\r\n" % header
            self.response_headers = response_headers
    
    
    
        def handle_client(self, client_socket):
            # 获取客户端请求
            request_data = client_socket.recv(1024)
            print(request_data)
    
            # 判断用户发来的请求
            # 使用splitlines来切割不同行
            request_lines = request_data.splitlines()
            for line in request_lines:
                print(line)
    
            # GET / HTTP/1.1
            request_start_line = request_lines[0]
            file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
            method = re.match(r"(\w+) +/[^ ]* ", request_start_line.decode("utf-8")).group(1)
    
            """在对web服务器改写过程中,判断用户请求数据是动态资源还是静态资源通通不管"""
    
            # time.py
            env = {
                "PATH_INFO": file_name,
                "METHOD": method
            }
            # 所有以上信息都由app中的路由进行转发
            response_body = self.app(env, self.start_response)
    
            response = self.response_headers + "\r\n" + response_body
    
            # 向客户端形响应数据
            client_socket.send(bytes(response, "utf-8"))
            # 关闭客户端连接
            client_socket.close()
    
        def bind(self, port):
            self.server_socket.bind(("", port))
    
    
    def main():
        sys.path.insert(1, WSGI_PYTHON_DIR)
        http_server = HTTPServer()
        # http_server.set_port()
        http_server.bind(8080)
        http_server.start()
    
    
    if __name__ == "__main__":
        main()
    

    相关文章

      网友评论

          本文标题:2018-06-11web框架编写

          本文链接:https://www.haomeiwen.com/subject/spskeftx.html