码迷,mamicode.com
首页 > Web开发 > 详细

BaseHTTPServer与CGIHTTPServer学习札记

时间:2015-01-28 22:42:14      阅读:358      评论:0      收藏:0      [点我收藏+]

标签:

今天学习了《Python核心编程》中Web服务器相关章节。于是走读了一下python的源码。

本人电脑上安装的是python2.6,相应的源码文件存放在 /usr/lib/python2.6/ 路径下。

1 BaseHTTPServer浅析

打开 /usr/lib/python2.6/BaseHTTPServer.py 文件。

1.1 HTTPServer类

最上面定义了类 HTTPServer,继承于 SocketServer.TCPServer,它不断接收数据,并将接收到的数据交给 RequestHandler 处理。

技术分享

它没有在TCPServer的基础上添加大量的功能,只加了一个server_bind()成员函数。


1.2 BaseHTTPRequestHandler类

看到类 BaseHTTPRequestHandler,这个类负责处理接收到的HTTP请求,如POST,GET之类的。

技术分享

看到它的成员函数 handle()

技术分享

请求处理就是调用handle()函数进行的。首先,它将类成员变量close_connection置为1,如果在handle_one_request()执行中没有将其置为0,那么handle()就返回了。

那在什么情况下close_connection会被置为0呢?如果请求的header里有 Connection:keep-alive时会被清0。见parse_request()中:

技术分享

从上面的while循环可以看到,如果close_connection为0,那么就继续执行handle_one_request(),直到close_connection为1为至。


那么 handle_one_request() 又在干什么呢?顾名思义,就是处理一个请求。

技术分享

L312:从rfile读取请求的数据,也就是HTTP报文数据。

L313~L315:如果读失败退出。

L316~L317:调用parse_request()对HTTP报文header进行解析,如果失败则退出。

L318:根据command,生成处理函数名,如GET命令生成的是do_GET。

L319~L323:检查当前类是否有 do_XXX() 成员函数,如果存在 do_XXX() 这个成员函数。


再看一下 parse_request() 是如何分析HTTP header的。主要分两步:

(1)读对报文数据的第一行,格式是:<命名> <路径> <HTTP版本>,通常是:“GET / HTTP/1.1”。

        分析版号是否正确,并解析出command, path, version,并保存到对应的成员变量中。

(2)检查headers是中的Connection,如果是keep-alive,那么就得将close_connection置为0,以保存连接。

技术分享


从对BaseHTTPRequestHandler的分析可以得知,如果我们要响应POST,GET命令,那必须得继承于BaseHTTPRequestHandler,并定义好do_GET()与do_POST()函数。

除了上述的三个重要的函数外,BaseHTTPRequestHandler 还提供了很多有用的成员函数:

send_error(code, message=None)

send_respond(code, message=None)

send_header(keyword, value)

end_headers()

...


2 CGIHTTPServer浅析

打开 /usr/lib/python2.6/CGIHTTPServer.py 文件。文件里只定义了一个 CGIHTTPRequestHandler 类,继承于 SimpleHTTPServerHandler。

其实 SimpleHTTPRequestHandler 是继承于 BaseHTTPRequestHandler 的。

技术分享

它实现了 do_POST() 函数:

技术分享

意思很简单,如果是CGI,那么就执行CGI,否则报错。

那怎么才算是CGI呢?我们跟踪一下 is_cgi() 函数:

技术分享

看起来很简单,也就是在目录 cgi_directories 下的文件,认为是cgi文件。在L89定义了 cgi_directories,也就是在 /cgi-bin 或 /htbin 目录下的都认为是 cgi。

_url_collapse_path_split(path) 函数是用于规整路径的,防止路径中出现过多 ./ 或 .. / 出现的防问漏洞。


那么怎么执行cgi的呢?我们一起跟一下 run_cgi() 函数。

待续……





















BaseHTTPServer与CGIHTTPServer学习札记

标签:

原文地址:http://my.oschina.net/hevakelcj/blog/372923

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!