zoukankan      html  css  js  c++  java
  • 一次请求到响应的整个流程

    一次请求到响应的整个流程

    As we all know,所有的Web应用,其本质上其实就是一个socket服务端,而用户的浏览器就是一个socket客户端。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/usr/bin/env python
    #coding:utf-8
        
    import socket
        
    def handle_request(client):
        buf = client.recv(1024)
        client.send("HTTP/1.1 200 OK ")
        client.send("Hello, Seven")
        
    def main():
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('localhost',8000))
        sock.listen(5)
        
        while True:
            connection, address = sock.accept()
            handle_request(connection)
            connection.close()
        
    if __name__ == '__main__':
        main()

      上述代码使用socket实现了其本质,对于所有的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,避免大家重复的造轮子,因此有人发明了相关的工具——Web框架,for example:Django、Flask、web.py  and so on。不同的框架可能采用不同的目录结构,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。以前,如何选择合适的Web应用程序框架成为困扰Python初学者的一个问题,这是因为,一般而言,Web应用框架的选择将限制可用的Web服务器的选择,反之亦然。那时的Python应用程序通常是为CGI,FastCGI,mod_python中的一个而设计,甚至是为特定Web服务器的自定义的API接口而设计的。

      PythonWeb服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是Python应用程序或框架和Web服务器之间的一种接口,已经被广泛接受, 它已基本达成它的可移植性方面的目标。

    WSGI 没有官方的实现, 因为WSGI更像一个协议. 只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。
      我们今天要讲的django web框架就需要使用wsgi,djano内部并没有实现socket,而是通过socket实现的。

    概述:

      Django的请求到响应的流程,简单的来说就是利用wsgi,当用户发来一个request进行response,响应前发送request_started信号,经过中间件的process_request,响应完成后会调用中间件的process_response。

    1.浏览器端用户用url发来了一个请求

      当django程序启动时,会根据settings中:

    源码截图:

    (注:这里是project名.wsgi.application,博主创建的project名为s3。)

    执行applicaion对应的函数:

    源码截图:

    接下来我们来看get_wsgi_application函数:

    源码截图:

    从上述源码可看出django每次请求响应都会返回一个WSGIHandler类的实例。

    WSGIHandler类源码截图:

    这里,我们需要关注的是:

        load_middleware只有第一次请求会调用,即中间件的加载只会在第一次请求时执行。

        WSGIhandler类中发送了request_started信号。

    下来我们首先关注一下他的父类base.BaseHandler类:

    base.BaseHandler类源码截图:

    中间件的完整执行流程图:

    备注:由上图可看出:

    • 当请求到来时,会首先经过中间件的Process_Request,如果Process_Request有return即当前url没有通过中间件,则程序直接跳转到最后一个Process_Response,然后逆序执行所有的Process_Response。
    • 然后程序会进入url,这时程序会检测用户有没有设置process_view,如果有,则接下来先执行process_view,如果process_view有return,则程序直接跳转到最后一个Process_Response,然后逆序执行所有的Process_Response。
    • 如果上一步没有process_view,程序会执行views文件中的函数
    • 执行完上一步,程序会检测有没有异常出现,如果有,则先执行中间件类对应的process_exception
    • 最后,程序会逆序执行所有的Process_Response。

    备注:request_middleware、view_middleware 是顺序执行,template_response_middleware、response_middleware、exception_middleware 是逆序执行。

    url:

    首先程序会根据配置文件中:

    源码截图:

    (同样这是是project名.urls)

    找到urls.py文件

    url匹配源码:

    这里直接使用当前url是否属于LocaleRegexURLResolver这个类。

    LocaleRegexURLResolver类:

    预编译:

    正则匹配:

    我们需要关注的是LocaleRegexURLResolver类的resolve方法:

    注:self.url_patterns是所有的正则url,这里对正则url进行循环;new_path是用户输入的url,这里pattern.resolve是执行RegexURLPattern类的resolve方法:

    由上述源码可看出RegexURLPattern类的resolve方法即通过regex.search进行具体的匹配操作,其中regex封装了re模块。

    我们定义的url:

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django.conf.urls import url
    from django.contrib import admin
    from APP01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^articles/(?P<year>[0-9]{4})/$', views.special_case_2003),
        url(r'^articles/([0-9]{4})/$', views.year_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]

    源码url截图:

    从上述源码中可看出url方法接收正则表达式和view两个参数,最终返回一个RegexURLPattern对象,RegexURLPattern类对正则表达式和view做进一步处理

     

    由上述源码可看出,在完成正则匹配后,view会被作为回调函数运行。由此解释了url是如何与views函数进行绑定的。

      接下来,程序调用views函数,并对模板进行渲染,并返回到view,程序如果没有异常,执行中间件的Process_Response(详见上文中间件的执行流程),最终程序发送一个信号 request_finished信号,订阅这个信号的事件会清空并释放任何使用中的资源。

       如果您觉得本文对您有参考价值,欢迎帮博主点击文章下方的推荐,谢谢!

  • 相关阅读:
    「JSOI2015」套娃
    「JSOI2015」非诚勿扰
    「JSOI2015」送礼物
    「JSOI2015」子集选取
    「JSOI2015」salesman
    「JSOI2015」字符串树
    [2]树的DFS序
    hdu 6058 Kanade's sum
    UVALive 6907 Body Building
    CF617/E XOR and Favorite Number
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5844313.html
Copyright © 2011-2022 走看看