python:http.server --- HTTP 服务器

  • 简介
  • 安全考量

简介

HTTPServer 是 socketserver.TCPServer 的一个子类。它会创建和侦听 HTTP 套接字,并将请求分发给处理程序。创建和运行 HTTP 服务器的代码类似如下所示:

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):server_address = ('', 8000)httpd = server_class(server_address, handler_class)httpd.serve_forever()
class http.server.HTTPServer(server_address, RequestHandlerClass)

该类基于 TCPServer 类,并在实例变量 server_name 和 server_port 中保存 HTTP 服务器地址。处理程序可通过实例变量 server 访问 HTTP 服务器。

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)
该类相似于 HTTPServer ,只是会利用 ThreadingMixIn 对请求进行多线程处理。当需要对 Web 浏览器预先打开套接字进行处理时,这就很有用,这时 HTTPServer 会一直等待请求。

3.7 新版功能.

实例化 HTTPServer 和 ThreadingHTTPServer 时,必须给出一个 RequestHandlerClass,本模块提供了该对象的三种变体:

class http.server.BaseHTTPRequestHandler(request, client_address, server)
这个类用于处理到达服务器的 HTTP 请求。 它本身无法响应任何实际的 HTTP 请求;它必须被子类化以处理每个请求方法(例如 GET 或 POST)。 BaseHTTPRequestHandler 提供了许多供子类使用的类和实例变量以及方法。

这个处理程序将解析请求和标头,然后调用特定请求类型对应的方法。 方法名称将根据请求来构造。 例如,对于请求方法 SPAM,将不带参数地调用 do_SPAM() 方法。 所有相关信息会被保存在该处理程序的实际变量中。 子类不需要重载或扩展 init() 方法。

BaseHTTPRequestHandler 具有下列实例变量:

client_address
包含 (host, port) 形式的指向客户端地址的元组。

server
包含服务器实例。

close_connection
应当在 handle_one_request() 返回之前设定的布尔值,指明是否要期待另一个请求,还是应当关闭连接。

requestline
包含 HTTP 请求行的字符串表示。 末尾的 CRLF 会被去除。 该属性应当由 handle_one_request() 来设定。 如果无有效请求行被处理,则它应当被设为空字符串。

command
包含具体的命令(请求类型)。 例如 ‘GET’。

path
包含请求路径。如果URL的查询部分存在, path 会包含这个查询部分。使用 RFC 3986 的术语来说,在这里, path 包含 hier-part 和 query 。

request_version
包含请求的版本字符串。 例如 ‘HTTP/1.0’。

headers
存放由 MessageClass 类变量所指定的类的实例。 该实例会解析并管理 HTTP 请求中的标头。 http.client 中的 parse_headers() 函数将被用来解析标头并且它需要 HTTP 请求提供一个有效的 RFC 2822 风格的标头。

rfile
一个 io.BufferedIOBase 输入流,准备从可选的输入数据的开头进行读取。

wfile
包含用于写入响应并发回给客户端的输出流。 在写入流时必须正确遵守 HTTP 协议以便成功地实现与 HTTP 客户端的互操作。

在 3.6 版更改: 这是一个 io.BufferedIOBase 流。

BaseHTTPRequestHandler 具有下列属性:

server_version
指定服务器软件版本。 你可能会想要重载该属性。 该属性的格式为多个以空格分隔的字符串,其中每个字符串的形式为 name[/version]。 例如 ‘BaseHTTP/0.2’。

sys_version
包含 Python 系统版本,采用 version_string 方法和 server_version 类变量所支持的形式。 例如 ‘Python/1.4’。

error_message_format
指定应当被 send_error() 方法用来构建发给客户端的错误响应的格式字符串。 该字符串应使用来自 responses 的变量根据传给 send_error() 的状态码来填充默认值。

error_content_type
指定发送给客户端的错误响应的 Content-Type HTTP 标头。 默认值为 ‘text/html’。

protocol_version
MessageClass
指定一个 email.message.Message 这样的类来解析 HTTP 标头。 通常该属性不会被重载,其默认值为 http.client.HTTPMessage。

responses
该属性包含一个整数错误代码与由短消息和长消息组成的二元组的映射。 例如,{code: (shortmessage, longmessage)}。 shortmessage 通常是作为消息响应中的 message 键,而 longmessage 则是作为 explain 键。 该属性会被 send_response_only() 和 send_error() 方法所使用。

BaseHTTPRequestHandler 实例具有下列方法:

handle()
调用 handle_one_request() 一次(或者如果启用了永久连接则为多次)来处理传入的 HTTP 请求。 你应该完全不需要重载它;而是要实现适当的 do_*() 方法。

handle_one_request()
此方法将解析并将请求分配给适当的 do_*() 方法。 你应该完全不需要重载它。

handle_expect_100()

3.2 新版功能.

send_error(code, message=None, explain=None)
发送并记录回复给客户端的完整错误信息。 数字形式的 code 指明 HTTP 错误代码,可选的 message 为简短的易于人类阅读的错误描述。 explain 参数可被用于提供更详细的错误信息;它将使用 error_message_format 属性来进行格式化并在一组完整的标头之后作为响应体被发送。 responses 属性存放了 message 和 explain 的默认值,它们将在未提供时被使用;对于未知代码两者的默认值均为字符串 ???。 如果方法为 HEAD 或响应代码是下列值之一则响应体将为空: 1xx, 204 No Content, 205 Reset Content, 304 Not Modified。

在 3.4 版更改: 错误响应包括一个 Content-Length 标头。 增加了 explain 参数。

send_response(code, message=None)
将一个响应标头添加到标头缓冲区并记录被接受的请求。 HTTP 响应行会被写入到内部缓冲区,后面是 Server 和 Date 标头。 这两个标头的值将分别通过 version_string() 和 date_time_string() 方法获取。 如果服务器不打算使用 send_header() 方法发送任何其他标头,则 send_response() 后面应该跟一个 end_headers() 调用。

在 3.3 版更改: 标头会被存储到内部缓冲区并且需要显式地调用 end_headers()。

send_header(keyword, value)
将 HTTP 标头添加到内部缓冲区,它将在 end_headers() 或 flush_headers() 被发起调用时写入输出流。 keyword 应当指定标头关键字,并以 value 指定其值。 请注意,在 send_header 调用结束之后,必须调用 end_headers() 以便完成操作。

在 3.2 版更改: 标头将被存入内部缓冲区。

send_response_only(code, message=None)
只发送响应标头,用于当 100 Continue 响应被服务器发送给客户端的场合。 标头不会被缓冲而是直接发送到输出流。 如果未指定 message,则会发送与响应 code 相对应的 HTTP 消息。

3.2 新版功能.

end_headers()
将一个空行(指明响应中 HTTP 标头的结束)添加到标头缓冲区并调用 flush_headers()。

在 3.2 版更改: 已缓冲的标头会被写入到输出流。

flush_headers()
最终将标头发送到输出流并清空内部标头缓冲区。

3.3 新版功能.

log_request(code=‘-’, size=‘-’)
记录一次被接受(成功)的请求。 code 应当指定与请求相关联的 HTTP 代码。 如果请求的大小可用,则它应当作为 size 形参传入。

log_error(…)
当请求无法完成时记录一次错误。 默认情况下,它会将消息传给 log_message(),因此它接受同样的参数 (format 和一些额外的值)。

log_message(format, …)
将任意一条消息记录到 sys.stderr。 此方法通常会被重载以创建自定义的错误日志记录机制。 format 参数是标准 printf 风格的格式字符串,其中会将传给 log_message() 的额外参数用作格式化操作的输入。 每条消息日志记录的开头都会加上客户端 IP 地址和当前日期时间。

version_string()
返回服务器软件的版本字符串。 该值为 server_version 与 sys_version 属性的组合。

date_time_string(timestamp=None)
返回由 timestamp 所给定的日期和时间(参数应为 None 或为 time.time() 所返回的格式),格式化为一个消息标头。 如果省略 timestamp,则会使用当前日期和时间。

结果看起来像 ‘Sun, 06 Nov 1994 08:49:37 GMT’。

log_date_time_string()
返回当前的日期和时间,为日志格式化

address_string()
返回客户端的地址

在 3.3 版更改: 在之前版本中,会执行一次名称查找。 为了避免名称解析的时延,现在将总是返回 IP 地址。

class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)
这个类会为目录 directory 及以下的文件提供发布服务,或者如果未提供 directory 则为当前目录,直接将目录结构映射到 HTTP 请求。

3.7 新版功能: directory 形参。

在 3.9 版更改: directory 形参接受一个 path-like object。

诸如解析请求之类的大量工作都是由基类 BaseHTTPRequestHandler 完成的。本类实现了 do_GET() 和 do_HEAD() 函数。

以下是 SimpleHTTPRequestHandler 的类属性。

server_version
这会是 “SimpleHTTP/” + version,其中 version 定义于模块级别。

extensions_map
将后缀映射为 MIME 类型的字典,其中包含了覆盖系统默认值的自定义映射关系。不区分大小写,因此字典键只应为小写值。

在 3.9 版更改: 此字典不再填充默认的系统映射,而只包含覆盖值。

SimpleHTTPRequestHandler 类定义了以下方法:

do_HEAD()
本方法为 ‘HEAD’ 请求提供服务:它将发送等同于 GET 请求的头文件。关于合法头部信息的更完整解释,请参阅 do_GET() 方法。

do_GET()
通过将请求解释为相对于当前工作目录的路径,将请求映射到某个本地文件。

如果请求被映射到目录,则会依次检查该目录是否存在 index.html 或 index.htm 文件。若存在则返回文件内容;否则会调用 list_directory() 方法生成目录列表。本方法将利用 os.listdir() 扫描目录,如果 listdir() 失败,则返回 404 出错应答。

如果请求被映射到文件,则会打开该文件。 打开文件时的任何 OSError 异常都会被映射为 404, ‘File not found’ 错误。 如果请求中带有 ‘If-Modified-Since’ 标头,而在此时间点之后文件未作修改,则会发送 304, ‘Not Modified’ 的响应。 否则会调用 guess_type() 方法猜测内容的类型,该方法会反过来用到 extensions_map 变量,并返回文件内容。

将会输出 ‘Content-type:’ 头部信息,带上猜出的内容类型,然后是 ‘Content-Length:’ 头部信息,带有文件的大小,以及 ‘Last-Modified:’ 头部信息,带有文件的修改时间。

后面是一个空行,标志着头部信息的结束,然后输出文件的内容。如果文件的 MIME 类型以 text/ 开头,文件将以文本模式打开;否则将使用二进制模式。

For example usage, see the implementation of the test function in Lib/http/server.py.

在 3.7 版更改: 为 ‘If-Modified-Since’ 头部信息提供支持。

SimpleHTTPRequestHandler 类的用法可如下所示,以便创建一个非常简单的 Web 服务,为相对于当前目录的文件提供服务:

import http.server
import socketserverPORT = 8000Handler = http.server.SimpleHTTPRequestHandlerwith socketserver.TCPServer(("", PORT), Handler) as httpd:print("serving at port", PORT)httpd.serve_forever()

http.server 也可以使用解释器的 -m 参数直接调用。 与前面的例子类似,这将提供相对于当前目录的文件:

python -m http.server
服务器默认监听端口为8000。可以通过传递所需的端口号作为参数来覆盖默认值:

python -m http.server 9000
默认情况下,服务器将自己绑定到所有接口。 选项 -b/–bind 指定了一个特定的地址,它应该与之绑定。 IPv4 和 IPv6 地址都被支持。例如,下面的命令使服务器只绑定到 localhost:

python -m http.server --bind 127.0.0.1
3.4 新版功能: 引入了 --bind 参数。

3.8 新版功能: 为了支持 IPv6 改进了 --bind 参数。

默认情况下,服务器使用当前目录。选项 -d/–directory 指定了一个它应该提供文件的目录。例如,下面的命令使用一个特定的目录:

python -m http.server --directory /tmp/
3.7 新版功能: --directory 参数被引入。

python -m http.server --protocol HTTP/1.1
3.11 新版功能: --protocol argument was introduced.

class http.server.CGIHTTPRequestHandler(request, client_address, server)
该类可为当前及以下目录中的文件或输出 CGI 脚本提供服务。注意,把 HTTP 分层结构映射到本地目录结构,这与 SimpleHTTPRequestHandler 完全一样。

备注 由 CGIHTTPRequestHandler 类运行的 CGI 脚本不能进行重定向操作(HTTP 代码302),因为在执行 CGI 脚本之前会发送代码 200(接下来就输出脚本)。这样状态码就冲突了。
然而,如果这个类猜测它是一个 CGI 脚本,那么就会运行该 CGI 脚本,而不是作为文件提供出去。 只会识别基于目录的 CGI —— 另有一种常用的服务器设置,即标识 CGI 脚本是通过特殊的扩展名。

如果请求指向 cgi_directories 以下的路径,do_GET() 和 do_HEAD() 函数已作修改,不是给出文件,而是运行 CGI 脚本并输出结果。

CGIHTTPRequestHandler 定义了以下数据成员:

cgi_directories
默认为 [‘/cgi-bin’, ‘/htbin’],视作 CGI 脚本所在目录。

CGIHTTPRequestHandler 定义了以下方法:

do_POST()
本方法服务于 ‘POST’ 请求,仅用于 CGI 脚本。如果试图向非 CGI 网址发送 POST 请求,则会输出错误 501:Can only POST to CGI scripts"。

请注意,为了保证安全性,CGI 脚本将以用户 nobody 的 UID 运行。CGI 脚本运行错误将被转换为错误 403。

通过在命令行传入 --cgi 参数,可以启用 CGIHTTPRequestHandler :

python -m http.server --cgi

安全考量

SimpleHTTPRequestHandler在处理请求时将遵循符号链接,这使得可以为指定目录之外的文件提供服务。

早期版本的Python没有清除从Python-m http.server或默认BaseHTTPRequestHandler.log_message实现发送到stderr的日志消息中的控制字符。这可能允许连接到服务器的远程客户端向您的终端发送恶意控制代码。

3.11.1 新版功能: 在stderr日志中清除控制字符。

python:http.server --- HTTP 服务器相关推荐

  1. Python http.server 服务器

    Python-simple-http-server 简介 这是一个轻量级的基于 Python http.server 编写的服务器,你可以非常容易的搭建一个 Restful API.其中一些请求的转发 ...

  2. python udp 大文件_Python UDP服务器发送文本文件的行(Python UDP Server send lines of a text file)...

    Python UDP服务器发送文本文件的行(Python UDP Server send lines of a text file) 我需要模拟一个UDP服务器,它在无限循环中逐行发送文本文件的内容. ...

  3. esp32 micropython web服务器_ESP32 Arduino教程:Websocket server(服务器)

    本文主要介绍如何使用Arduino内核作为编程架构在ESP32(上创建Websocket server(服务器).所创建的Websocket server(服务器)将作为回发服务器使用,也就是说它会把 ...

  4. python快速部署一个服务器_Python加Shell快速部署集群

    最近痛感在集群里逐台部署ganglia, cacti这些监控的东西很麻烦,就写了个小程序去批量自动部署.原理是通过Python的pexpect用ssh去复制文件和执行系统命令,我用它来部署gangli ...

  5. python 播放视频 ftp_利用Python快速搭建HTTPFTP服务器

    用 Python 快速实现 FTP 服务器 有时当你想快速搭建一个 FTP 服务器来临时实现文件上传下载时,这是特别有用的.我们这里利用 Python 的Pyftpdlib 模块可以快速的实现一个 F ...

  6. python自动化部署程序,聊聊Python自动化脚本部署服务器全流程(详细)

    原标题:聊聊Python自动化脚本部署服务器全流程(详细) 来源:AirPython 作者:星安果 1. 前言 大家好,我是安果! 日常编写的 Python 自动化程序,如果在本地运行稳定后,就可以考 ...

  7. python批量上传 服务器_Python Tornado批量上传图片并显示功能

    简介 Tornado龙卷风是一个开源的网络服务器框架,它是基于社交聚合网站FriendFeed的实时信息服务开发而来的.2007年由4名Google前软件工程师一起创办了FriendFeed,旨在使用 ...

  8. Python实现web动态服务器

    Python实现http动态服务器,有两种方法,一种是基本的实现方式,可扩展性差,但是是实现服务器的基础,第二种实现不修改服务器和架构代码而确保可以在多个架构下运行web服务器.都使用WSGI(Web ...

  9. cdt规约报文用程序解析_用 Python 撸一个 Web 服务器第3章:使用 MVC 构建程序

    Todo List 程序介绍 我们将要编写的 Todo List 程序包含四个页面,分别是注册页面.登录页面.首页.编辑页面.以下分别为四个页面的截图. 注册页面: 登录页面: 首页: 编辑页面: 程 ...

最新文章

  1. 收藏 不显示删除回复显示所有回复显示星级回复显示得分回复 有损脑健康的七种坏习惯...
  2. 交叉编译Open***-2.4.3
  3. jquery.desktop.js 代码分析
  4. springboot异步注解_SpringBoot如何实现异步、定时任务?
  5. SAP 电商云 Spartacus UI Quick Order 的路由和 CMS 实现
  6. 高中经历——高考专业被调剂毁了童年梦想
  7. 分组后分页_SQL(约束、视图、分页、序列、索引、同义词、创建用户,为用户授权、执行计划的使用 数据的导入导出)...
  8. docker 虚拟化_如果没有虚拟化,Docker将提供什么?
  9. 后置递增运算符(JS)
  10. UDP是全双工通信的吗
  11. Unsplash能找到很多免费无版权图片
  12. 程序员客栈统计:2021年中国程序员薪资和生活现状调查报告
  13. 对哈夫曼编码的输出 c语言,哈夫曼编码问题
  14. 小爱同学定制语音包分享_小爱同学音色定制链接
  15. tomcat使用cronolog进行日志切割
  16. 第1115期AI100_机器学习日报(2017-10-07)
  17. Python实现摄像头状态巡检
  18. Android端使用FFmpeg进行视频画面拼接
  19. 6套毕业设计PPT模板拯救你的毕业答辩
  20. B. Ugu codeforces 1732B

热门文章

  1. errno、stderr、perror函数和strerror函数
  2. 搜索与图论模板题(必备)Day3
  3. 21 个好用的持续集成工具,总有一款适合你
  4. OAuth2之授权服务
  5. php artisan 出错,使用php artisan serve命令获取错误
  6. STM32标准库、HAL库特点与应用
  7. C++进阶之路《C11新特性》
  8. 项目leader如何把控团队氛围
  9. python 实现自动化
  10. 重新启动遇到错误导致系统安装无法继续