python-3.x - Chrome 发出阻止请求
问题描述
我做了一个完全重复我的代码行为的最小示例。我从 Firefox 和 chrome 提出请求。我注意到在向 chrome 发出请求后,Firefox 停止接收答案。经过一番研究,我意识到服务器响应 localhost:8000/favicon.ico 路径请求时出错。收到一次错误404后,chrome在服务器每次响应后都会创建另一个到服务器的连接,但不发送数据,这会导致recv函数被锁定。
File "/usr/lib/python3.7/socket.py", line 589, in readinto
return self._sock.recv_into(b)
我发现我可以为处理程序类设置连接超时,它在 StreamRequestHandler:r 中被考虑在内:
if self.timeout is not None:
self.connection.settimeout(self.timeout)
但是我很尴尬,文档中没有关于此的信息 https://docs.python.org/3/library/socketserver.html#socketserver.BaseRequestHandler.handle
import logging
import json
import http.server
from http import HTTPStatus
from typing import Optional
from urllib.parse import urlparse, parse_qs
import socketserver
from threading import Thread
import traceback
from functools import wraps
import sys, os
project_dir = os.path.abspath(os.curdir)
sys.path.append(project_dir)
logging.getLogger().setLevel("DEBUG")
class RESTHandler(http.server.BaseHTTPRequestHandler):
"""
Rest router for api methods
"""
def __init__(self, *args, **kwargs):
logging.info(f"Creating RESTHandler obj. Args: {args}, kwargs: {kwargs}")
super().__init__(*args, **kwargs)
def end_headers(self) -> None:
self.send_header('Access-Control-Allow-Origin', '*')
http.server.BaseHTTPRequestHandler.end_headers(self)
# noinspection PyPep8Naming
def do_GET(self):
logging.info(self.path)
url = urlparse(self.path)
if "favicon.ico" in url.path:
self.send_error(HTTPStatus.NOT_FOUND, message='Unknown api path.')
return
self.send_response(HTTPStatus.OK)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"resp":"I am OK", "int": 5}, ensure_ascii=False).encode('utf-8'))
class ApiService():
DEFAULT_API_PORT = 8000
DEFAULT_API_HOST = ''
def __init__(self, ui_service = None, host: Optional[str] = None, port: Optional[int] = None):
self.ui_service = ui_service
self.host = host or self.DEFAULT_API_HOST
self.port = port or self.DEFAULT_API_PORT
def _run(self):
while True:
try:
with socketserver.TCPServer((self.host, self.port), RESTHandler, bind_and_activate=False) as httpd:
logging.info("Starting server....")
httpd.allow_reuse_address = True
httpd.server_bind()
httpd.server_activate()
logging.info(f"Serving API at {self.host}:{self.port}")
httpd.serve_forever()
break
except Exception as e:
tb_list = traceback.format_exception( type(e), e, tb=e.__traceback__)
tb_list = [ s.replace("\n", "") for s in tb_list ]
tb_str = "; ".join(tb_list)
logging.error(f"Unexpected exception while http-server was working: {tb_str}")
def run(self, in_thread=True):
if in_thread:
t = Thread(target=self._run)
t.start()
else:
self._run()
if __name__ == '__main__':
ApiService().run(in_thread=False)
解决方案
我想,Chrome 使用网络浏览器预先打开套接字,在我的情况下 TCPServer 会无限期地等待。但我仍然很有趣,为什么只有在 404 之后以及使用请求处理程序超时的合法性如何。
推荐阅读
- javascript - javascript-关于玩家模拟运动的移动世界
- javascript - Heruko 部署无法读取未定义的属性位置?
- c# - 如何在 OnModelCreating 中减少 Fluent API 的代码
- python - 如何设置对象的 UV 纹理坐标并使用 python 计算切线空间?
- go - 如何从多个 goroutine 共享的单个通道中读取
- sql-server - SQL Server 位数组
- youtube-api - Youtube API V3;视频的最大数量只有 50?
- android - Adding fragment into framelayout cause support-actionbar hiding
- c++ - C ++ ostream没有创建新文件
- wpf - How to animate Button's Content property with Image control