21人参与 • 2025-08-20 • Python
win11专业版
python 3.9
# -*- coding:utf-8 -*- import json import traceback import uuid from http.server import httpserver, threadinghttpserver, basehttprequesthandler from urllib.parse import urlparse, parse_qs class myhttprequesthandler(basehttprequesthandler): def _send_response(self, status_code, content_type, body): '''发送响应信息''' self.send_response(status_code) self.send_header('content-type', content_type) self.send_header('cache-control', 'no-store') # 防止缓存旧编码响应 self.end_headers() self.wfile.write(body.encode('utf-8')) def _handle_home(self): '''访问主页请求处理''' html = '<meta http-equiv="content-type" content="text/html; charset=utf-8"><h1>home page</h1>' self._send_response(200, 'text/html; charset=utf-8', html) def _handle_404(self): '''请求不存在资源处理''' # json_respose = {"success": false, "message": "not found"} # self._send_response(404, 'application/json;charset=utf-8', json.dumps(json_respose)) # content-type 指定 charset=utf-8 可避免浏览器get请求,界面中文显示乱码问题 self._send_response(404, 'text/html; charset=utf-8', "<h1>404 not found</h1>") def _handle_login(self, login_req_data): '''处理登录请求''' try: data = json.loads(login_req_data) username = data.get('username') password = data.get('password') ip = data.get('ip') response = { 'code': 0, 'token': uuid.uuid4().hex, 'description': 'success' } self._send_response(200, 'application/json; charset=utf-8', json.dumps(response)) except exception as e: error_msg = traceback.format_exc() print(error_msg) response = { 'code': 1, 'token': '', 'description': error_msg } self._send_response(500, 'application/json; charset=utf-8', json.dumps(response)) def do_get(self): '''处理get请求''' parsed_path = urlparse(self.path) path = parsed_path.path query_params = parse_qs(parsed_path.query) # 获取url携带的查询参数 # print('收到get请求参数:', query_params) if path == '/': self._handle_home() else: self._handle_404() def do_post(self): '''处理post请求''' content_length = int(self.headers['content-length']) post_data = self.rfile.read(content_length) parsed_path = urlparse(self.path) path = parsed_path.path query_params = parse_qs(parsed_path.query) # 获取url 查询参数 # print("收到post数据:", post_data.decode()) # 路由匹配逻辑 if path == '/': self._handle_home() elif path == '/north/login': self._handle_login(post_data.decode()) else: self._handle_404() if __name__ == '__main__': # server = httpserver(('0.0.0.0', 8000), myhandler) # 阻塞式运行 server = threadinghttpserver(('localhost', 8000), myhttprequesthandler) print('正在启动服务,访问地址:http://localhost:8000') server.serve_forever()
扩展:如果我们希望服务在处理请求的时,调用其它类实例的方法,或者更新其它类实例的属性,咋处理呢?
答案:将其它类实例初始化为requesthandler
的类属性,然后在相关请求处理函数中进行调用
示例
class subsystem(): def __init__(self, http_server_port): self.http_server_port = http_server_port self.server = threadinghttpserver(('0.0.0.0', self.http_server_port), lambda *args: myhttprequesthandler(self, *args)) self.north_server_info = {} def start_http_server(self): self.server.serve_forever() def push_data(self, data): '''测试函数''' logger.info(f'pushing data to server') def update_north_server_info(self, data): '''测试函数''' self.north_server_info[data.get('ip')] = data class myhttprequesthandler(basehttprequesthandler): def __init__(self, subsystem, *args, **kwargs): self.subsystem = subsystem # 保存subsystem实例引用 super().__init__(*args, **kwargs) # ....略 def _handle_login(self, login_req_data): '''处理登录请求''' try: data = json.loads(login_req_data) username = data.get('username') password = data.get('password') ip = data.get('ip') response = { 'code': 0, 'token': uuid.uuid4().hex, 'description': 'success' } self.subsystem.push_data('') self.subsystem.update_north_server_info({'username': username, 'password': password, 'ip': ip}) self._send_response(200, 'application/json; charset=utf-8', json.dumps(response)) except exception as e: error_msg = traceback.format_exc() logger.error(error_msg) response = { 'code': 1, 'token':'', 'description': error_msg } self._send_response(500, 'application/json; charset=utf-8', json.dumps(response)) # 测试 if __name__ == '__main__': http_port = 8000 for i in range(2): system = subsystem(http_port) thread = threading.thread(target=system.start_http_server) thread.start() http_port += 1
http.server 模块定义了用于实现http服务器(web服务器)的类。
其中一个类,httpserver
是socketserver.tcpserver
子类。它创建并监听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)
server_name
和server_port
的实例变量。通过handler访问服务,通常是通过handler的server
实例变量class http.server.threadinghttpserver(server_address, requesthandlerclass)
httpserver
一样,除了通过使用 threadingmixin使用线程处理请求。 3.7版本中新增httpserver 和threadinghttpserver 必须在实例化时给它一个requesthandlerclass,此模块提供了三种不同的变体:
class http.server.basehttprequesthandler(request, client_address, server)
get
或post
)。basehttprequesthandler
提供了许多类和实例变量以及子类使用的方法。basehttprequesthandler
实例变量:basehttprequesthandler
属性:basehttprequesthandler
实例方法:client_address
(host, port)
形式,表示客户端地址的元组server
close_connection
requestline
crlf
。此属性应通过[handle_one_request()
设置。如果没有处理有效的请求行,则应将其设置为空字符串。command
'get'
.path
path
包括查询参数。request_version
headers
rfile
wfile
server_version
name[/version]
。例如,'basehttp/0.2'
。sys_version
version_string
方法及 server_version
]类变量使用的相同。例如,'python/1.4'
。error_message_format
send_error()
应使用的格式字符串,用于构建对客户端的错误响应的。默认情况下,基于传递给send_error
的状态代码,用responds
中的变量填充该字符串。error_content_type
content-type
http请求头。默认值为 'text/html'
。protocol_version
'http/1.1'
,服务器将允许http持久连接;但是,服务器在对客户端的所有响应中必须包含一个准确的content-length
请求头(使用send_header()
)。为了向后兼容,设置默认为“http/1.0”。messageclass
http.client.httpmessage
。responses
{code: (shortmessage, longmessage)}
。*shortmessage*
通常用作错误响应中的message
键,longmessage
用作explain
键。供send_response_only
和send_error()
方法使用。handle
()handle_one_request()
实现适当的do_*()
方法。handle_one_request
()do_*()
方法。你应永远不需要重写它。handle_expect_100
()expect: 100-continue
请求头时,它会以 100 continue
和“ 200 ok
头作为响应。如果服务器不希望客户端继续,则可以重写此方法以引发错误。例如,服务器可以选择发送417 expectation failed
作为响应头,并返回false
。send_error
(code, message=none, explain=none)???
。如果方法是head
或响应代码是以下代码之一:1xx
, 204 no content
, 205 reset content
, 304 not modified
,则请求体将为空。content-length
头。添加了explain参数。send_response
(code, message=none)send_header()
发送任何其他请求头,则send_response()
后面应该跟一个end_headers()调用。end_headers()
。send_header
(keyword, value)end_headers()
或者flush_headers()
被调用时,该缓冲区中的内容将被写入到输出流。keyword应指定header,value指定其值。请注意,在send_headers
调用完成后,必须调用end_headers()
才能完成操作。send_response_only
(code, message=none)100 continue
响应时使用。响应头未缓冲,直接发送到输出流。如果未指定message,则发送与响应code对应的http消息。end_headers
()flush_headers()
。flush_headers
()log_request
(code='-', 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)none
或采用time.time()
返回的格式),格式化为消息头。如果省略timestamp,则使用当前日期和时间。结果看起来像'sun, 06 nov 1994 08:49:37 gmt'
。log_date_time_string
()address_string
()class http.server.simplehttprequesthandler(request, client_address, server, directory=none)
class http.server.``cgihttprequesthandler(*request*, client_address, server)
https://docs.python.org/3.9/library/http.server.html
到此这篇关于python 基于http.server模块实现简单http服务的文章就介绍到这了,更多相关python http.server模块http服务内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论