zoukankan      html  css  js  c++  java
  • 二、Web框架实现

    一、简单web(socket)

    在前一篇WEB框架概述一文中已经详细了解了:从浏览器键入一个URL到返回HTML内容的整个过程。说到底,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

    最简单的Hello World程序如下:

    import socket
    
    HOST = ''
    PORT = 80
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.bind((HOST, PORT))
    listen_socket.listen(1)
    connection, address = listen_socket.accept()
    request = connection.recv(1024)
    connection.sendall(b"""HTTP/1.1 200 OK
    Content-type: text/html
     
    <html>
        <body>
            <h1>Hello, World!</h1>
        </body>
    </html>""")
    connection.close()
    

     

    这个代码接收简单的连接和一个客户端单一的请求,不管请求的 URL 是什么,它都会响应 HTTP 200(所以,这并不是一个真正意义上的 web 服务器)。Content-type:text/html 行代码的是 header 字段,header 用来提供请求或者响应的元信息。

    我们从浏览器请求,可以得到如下结果:

    这就是最简单的WEB应用。

    如果要动态生成HTML,就需要把上述步骤自己来实现,每次定义发送和接受的内容。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。这个接口就是前面介绍过的WSGIWeb Server Gateway Interface。WSGI就是一种协议,描述web server(uwsgi)如何与web application(app)通信的规范。serverapplication的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有BottleFlaskDjango

    当然,在python中,我们可以通过WSGIref来演示一个WEB框架的实现过程。

    二、Web框架实现(Wsgiref)

    Wsgiref库我们在前面已经有详细认识,所以这里不再介绍。

    通过Wsgiref实现一个简单的WEB sever如下:

    from wsgiref.simple_server import make_server
    #1、符合WSGI规范的application
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b'<h1>Hello, world!</h1>']
    
    #2、Wsgiref定义启动server httpd = make_server('', 80, application) print('Serving HTTP on port 80...')
    #3、开始监听HTTP请求: httpd.serve_forever()

      用户访问结果如下:

    我们从Wsgiref一文中了解到,environ其实是收集了一些环境变量(包括服务端的环境变量、客户端的请求信息以及wsgi信息),我们可以将其打印出来,添加代码:

    for k,v in environ.items():
    print k,v
    TMP C:UsersadminAppDataLocalTemp
    PYTHONIOENCODING UTF-8
    COMPUTERNAME ADMIN-PC
    wsgi.multiprocess False
    _OLD_VIRTUAL_PATH C:ProgramDataOracleJavajavapath;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;D:install softpython2.7
    USERDOMAIN admin-PC
    SERVER_PROTOCOL HTTP/1.1
    SERVER_SOFTWARE WSGIServer/0.1 Python/2.7.15
    PSMODULEPATH C:Windowssystem32WindowsPowerShellv1.0Modules
    SCRIPT_NAME 
    COMMONPROGRAMFILES C:Program FilesCommon Files
    PROCESSOR_IDENTIFIER Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
    REQUEST_METHOD GET
    PROGRAMFILES C:Program Files
    PROCESSOR_REVISION 3a09
    PATH C:ProgramDataOracleJavajavapath;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;D:install softpython2.7;D:xuequnvenvScripts
    QUERY_STRING 
    SYSTEMROOT C:Windows
    PYTHONUNBUFFERED 1
    PROGRAMFILES(X86) C:Program Files (x86)
    WINDOWS_TRACING_FLAGS 3
    CONTENT_LENGTH 
    HTTP_UPGRADE_INSECURE_REQUESTS 1
    VIRTUAL_ENV D:xuequnvenv
    HTTP_CACHE_CONTROL max-age=0
    HTTP_CONNECTION keep-alive
    TEMP C:UsersadminAppDataLocalTemp
    REMOTE_ADDR 127.0.0.1
    COMMONPROGRAMFILES(X86) C:Program Files (x86)Common Files
    PROCESSOR_ARCHITECTURE AMD64
    wsgi.url_scheme http
    ALLUSERSPROFILE C:ProgramData
    SERVER_PORT 80
    LOCALAPPDATA C:UsersadminAppDataLocal
    HOMEPATH Usersadmin
    PYCHARM_MATPLOTLIB_PORT 50538
    PROGRAMW6432 C:Program Files
    USERNAME admin
    HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    LOGONSERVER \ADMIN-PC
    PROMPT (venv) $P$G
    COMSPEC C:Windowssystem32cmd.exe
    PROGRAMDATA C:ProgramData
    PYTHONPATH D:install softpycharmPyCharm 2018.1.4helperspycharm_matplotlib_backend;D:xuequn
    wsgi.multithread True
    wsgi.input <socket._fileobject object at 0x0000000002900B10>
    HTTP_USER_AGENT Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
    HTTP_HOST localhost
    SESSIONNAME Console
    PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    PATH_INFO /
    FP_NO_HOST_CHECK NO
    WINDIR C:Windows
    wsgi.file_wrapper wsgiref.util.FileWrapper
    HTTP_ACCEPT_ENCODING gzip, deflate, br
    wsgi.version (1, 0)
    APPDATA C:UsersadminAppDataRoaming
    HOMEDRIVE C:
    SERVER_NAME admin-PC
    wsgi.run_once False
    REMOTE_HOST admin-PC
    SYSTEMDRIVE C:
    GATEWAY_INTERFACE CGI/1.1
    HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.9,en;q=0.8
    PYCHARM_HOSTED 1
    NUMBER_OF_PROCESSORS 4
    _OLD_VIRTUAL_PROMPT $P$G
    PROCESSOR_LEVEL 6
    CONTENT_TYPE text/plain
    wsgi.errors <open file '<stderr>', mode 'w' at 0x0000000001D62150>
    COMMONPROGRAMW6432 C:Program FilesCommon Files
    OS Windows_NT
    PUBLIC C:UsersPublic
    USERPROFILE C:Usersadmin
    TMP C:UsersadminAppDataLocalTemp
    PYTHONIOENCODING UTF-8
    COMPUTERNAME ADMIN-PC
    wsgi.multiprocess False
    _OLD_VIRTUAL_PATH C:ProgramDataOracleJavajavapath;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;D:install softpython2.7
    HTTP_REFERER http://localhost/
    USERDOMAIN admin-PC
    SERVER_PROTOCOL HTTP/1.1
    SERVER_SOFTWARE WSGIServer/0.1 Python/2.7.15
    PSMODULEPATH C:Windowssystem32WindowsPowerShellv1.0Modules
    SCRIPT_NAME 
    COMMONPROGRAMFILES C:Program FilesCommon Files
    PROCESSOR_IDENTIFIER Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
    REQUEST_METHOD GET
    PROGRAMFILES C:Program Files
    PROCESSOR_REVISION 3a09
    PATH C:ProgramDataOracleJavajavapath;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;D:install softpython2.7;D:xuequnvenvScripts
    QUERY_STRING 
    SYSTEMROOT C:Windows
    PYTHONUNBUFFERED 1
    PROGRAMFILES(X86) C:Program Files (x86)
    WINDOWS_TRACING_FLAGS 3
    CONTENT_LENGTH 
    VIRTUAL_ENV D:xuequnvenv
    HTTP_CACHE_CONTROL no-cache
    HTTP_CONNECTION keep-alive
    TEMP C:UsersadminAppDataLocalTemp
    REMOTE_ADDR 127.0.0.1
    COMMONPROGRAMFILES(X86) C:Program Files (x86)Common Files
    PROCESSOR_ARCHITECTURE AMD64
    wsgi.url_scheme http
    ALLUSERSPROFILE C:ProgramData
    SERVER_PORT 80
    LOCALAPPDATA C:UsersadminAppDataLocal
    HOMEPATH Usersadmin
    PYCHARM_MATPLOTLIB_PORT 50538
    PROGRAMW6432 C:Program Files
    USERNAME admin
    HTTP_ACCEPT image/webp,image/apng,image/*,*/*;q=0.8
    LOGONSERVER \ADMIN-PC
    PROMPT (venv) $P$G
    COMSPEC C:Windowssystem32cmd.exe
    PROGRAMDATA C:ProgramData
    PYTHONPATH D:install softpycharmPyCharm 2018.1.4helperspycharm_matplotlib_backend;D:xuequn
    wsgi.multithread True
    wsgi.input <socket._fileobject object at 0x0000000002900B10>
    HTTP_USER_AGENT Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
    HTTP_HOST localhost
    SESSIONNAME Console
    PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    PATH_INFO /favicon.ico
    FP_NO_HOST_CHECK NO
    WINDIR C:Windows
    wsgi.file_wrapper wsgiref.util.FileWrapper
    HTTP_ACCEPT_ENCODING gzip, deflate, br
    wsgi.version (1, 0)
    APPDATA C:UsersadminAppDataRoaming
    HOMEDRIVE C:
    SERVER_NAME admin-PC
    wsgi.run_once False
    REMOTE_HOST admin-PC
    SYSTEMDRIVE C:
    GATEWAY_INTERFACE CGI/1.1
    HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.9,en;q=0.8
    PYCHARM_HOSTED 1
    NUMBER_OF_PROCESSORS 4
    _OLD_VIRTUAL_PROMPT $P$G
    PROCESSOR_LEVEL 6
    HTTP_PRAGMA no-cache
    CONTENT_TYPE text/plain
    wsgi.errors <open file '<stderr>', mode 'w' at 0x0000000001D62150>
    COMMONPROGRAMW6432 C:Program FilesCommon Files
    OS Windows_NT
    PUBLIC C:UsersPublic
    USERPROFILE C:Usersadmin
    

      

     以上是实现了一个简单的请求和响应的过程,但是每次请求都是响应的固定不变的内容(hello world!)。现实当中,我们肯定希望是动态的内容,而且一般是通过请求不同的URL来返回不同的HTML内容。

    所以,我们需要解决动态路由的问题。

    从上面的基本信息中我们可以找到一个非常有用的信息:PATH_INFO。其实,这个变量就是代表了当前请求的URL。返回的内容我们可以很容易解决,通过函数返回不同的HTML内容就可以了。

    #coding:utf-8
    from wsgiref.simple_server import make_server
    
    def user():
        return ['<h1>hello jay!</h1>']
    
    def test():
        return ['<h1>Just  a test</h1>']
    
    url_map = {'user':user,'test':test} #Flask里面就是通过url_map进行URL对象保存
    
    def application(environ, start_response):
        path=environ['PATH_INFO'].split('/')[1]
        start_response('200 OK', [('Content-Type', 'text/html')])
    
        if path in url_map: #这里比较LowB了,Flask里面会把URL和视图函数进行绑定。
            return url_map[path]()
        else:
            return ["<h1>Page 404,not found!</h1>".encode("utf8")]
    
    httpd = make_server('', 80, application)
    print('Serving HTTP on port 80...')
    # 开始监听HTTP请求:
    httpd.serve_forever()
    

      

      这样,我们就把用户通过不同URL访问的内容进行了不同的响应,效果如下:

     当然,如果是真实环境下,我们会从数据库中获取数据,把固定的内容替换成可变的HTML内容,这样一个简单的web框架就成型了,是不是So easy?

  • 相关阅读:
    P1144 最短路计数 题解 最短路应用题
    C++高精度加减乘除模板
    HDU3746 Teacher YYF 题解 KMP算法
    POJ3080 Blue Jeans 题解 KMP算法
    POJ2185 Milking Grid 题解 KMP算法
    POJ2752 Seek the Name, Seek the Fame 题解 KMP算法
    POJ2406 Power Strings 题解 KMP算法
    HDU2087 剪花布条 题解 KMP算法
    eclipse创建maven项目(详细)
    maven的作用及优势
  • 原文地址:https://www.cnblogs.com/skyflask/p/9292101.html
Copyright © 2011-2022 走看看