英文:
Set protocol version for custom handler based on SimpleHTTPRequestHandler
问题
我基于Python的`http.server`模块创建了自己的脚本。脚本的主要目标是处理自定义路径"/files",以获取文件列表的JSON格式。
在Python 3.11中为`http.server`模块添加了`--protocol`参数。我使用的是Python 3.11.4。我试图以以下方式在我的脚本中支持此参数:
```python
import json
import os
import sys
from functools import partial
from http.server import SimpleHTTPRequestHandler, test
from pathlib import Path
class HTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self) -> None:
if self.path == '/files':
response = bytes(self._get_response(), 'utf-8')
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Content-Length', str(len(response)))
self.end_headers()
self.wfile.write(response)
return
return super().do_GET()
def _get_response(self) -> str:
results = []
for item in Path(self.directory).rglob('*'):
if item.is_file():
if __file__ in str(item):
continue
file_size = str(os.stat(item).st_size)
relative_file_path = os.path.relpath(item, self.directory)
if sys.platform == 'win32':
relative_file_path = relative_file_path.replace('\\', '/')
results.append(dict(file=relative_file_path, size=file_size))
return json.dumps(results)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b', '--bind', metavar='ADDRESS',
help='绑定到此地址 (默认: 所有接口)')
parser.add_argument('-d', '--directory', default=os.getcwd(),
help='提供此目录 (默认: 当前目录)')
parser.add_argument('-p', '--protocol', metavar='VERSION',
default='HTTP/1.1',
help='符合此HTTP版本 (默认: %(default)s)')
parser.add_argument('port', default=8000, type=int, nargs='?',
help='绑定到此端口 (默认: %(default)s)')
args = parser.parse_args()
handler_class = partial(HTTPRequestHandler, directory=args.directory)
test(HandlerClass=handler_class, port=args.port, bind=args.bind, protocol=args.protocol)
python server.py --bind <ip> <port> -p HTTP/1.1
但由于某种原因,响应头仍然包含"HTTP/1.0"版本。您能否请教我哪里出错了?
<details>
<summary>英文:</summary>
I've created my own script based on Python `http.server` module. The main target of script is handling custom path "/files" to get list of files in JSON format.
Parameter `--protocol` was added in Python 3.11 for `http.server` module. I use Python 3.11.4. I'm trying to support this parameter in my script in the following way:
```python
import json
import os
import sys
from functools import partial
from http.server import SimpleHTTPRequestHandler, test
from pathlib import Path
class HTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self) -> None:
if self.path == '/files':
response = bytes(self._get_response(), 'utf-8')
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Content-Length', str(len(response)))
self.end_headers()
self.wfile.write(response)
return
return super().do_GET()
def _get_response(self) -> str:
results = []
for item in Path(self.directory).rglob('*'):
if item.is_file():
if __file__ in str(item):
continue
file_size = str(os.stat(item).st_size)
relative_file_path = os.path.relpath(item, self.directory)
if sys.platform == 'win32':
relative_file_path = relative_file_path.replace('\\', '/')
results.append(dict(file=relative_file_path, size=file_size))
return json.dumps(results)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b', '--bind', metavar='ADDRESS',
help='bind to this address '
'(default: all interfaces)')
parser.add_argument('-d', '--directory', default=os.getcwd(),
help='serve this directory '
'(default: current directory)')
parser.add_argument('-p', '--protocol', metavar='VERSION',
default='HTTP/1.1',
help='conform to this HTTP version '
'(default: %(default)s)')
parser.add_argument('port', default=8000, type=int, nargs='?',
help='bind to this port '
'(default: %(default)s)')
args = parser.parse_args()
handler_class = partial(HTTPRequestHandler, directory=args.directory)
test(HandlerClass=handler_class, port=args.port, bind=args.bind, protocol=args.protocol)
python server.py --bind <ip> <port> -p HTTP/1.1
But by some reason response header still contains "HTTP/1.0" version.
Could you please advice what I'm doing wrong?
答案1
得分: 1
创建TCPServer实例,并在HTTPRequestHandler类上设置protocol_version
为"HTTP/1.1",然后在运行时它将使用HTTP/1.1。
from socketserver import TCPServer
...
handler_class = partial(HTTPRequestHandler, directory=args.directory)
HTTPRequestHandler.protocol_version = args.protocol
PORT = args.port
with TCPServer(("", PORT), handler_class) as httpd:
print("在端口上提供HTTP服务", PORT)
httpd.serve_forever()
如果调用http.server.test()函数,那么它会设置提供的HandlerClass参数上的protocol_version,但如果使用partial来包装类,则不起作用,因此必须显式设置HTTPRequestHandler.protocol_version
。
英文:
Create TCPServer instance and set protocol_version
on the HTTPRequestHandler class to "HTTP/1.1" then it uses HTTP/1.1 when running.
from socketserver import TCPServer
...
handler_class = partial(HTTPRequestHandler, directory=args.directory)
HTTPRequestHandler.protocol_version = args.protocol
PORT = args.port
with TCPServer(("", PORT), handler_class) as httpd:
print("Serving HTTP on port", PORT)
httpd.serve_forever()
If call http.server.test() function then it sets protocol_version on the provided HandlerClass argument, but won't work if using a partial
to wrap the class so must explicitly set HTTPRequestHandler.protocol_version
.
答案2
得分: 0
问题通过为自定义处理程序设置protocol_version
的值来解决:
...
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b', '--bind', metavar='ADDRESS',
help='绑定到此地址 '
'(默认:所有接口)')
parser.add_argument('-d', '--directory', default=os.getcwd(),
help='提供此目录 '
'(默认:当前目录)')
# --protocol 参数在 Python 3.11+ 中引入
parser.add_argument('-p', '--protocol', metavar='VERSION',
default='HTTP/1.1',
help='符合此 HTTP 版本 '
'(默认:%(default)s)')
parser.add_argument('port', default=8000, type=int, nargs='?',
help='绑定到此端口 '
'(默认:%(default)s)')
args = parser.parse_args()
HTTPRequestHandler.protocol_version = args.protocol
handler_class = partial(HTTPRequestHandler, directory=args.directory)
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
请注意,我已经将代码中的注释翻译成中文。
英文:
Problem was solved by setting value for protocol_version
on the custom handler:
...
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b', '--bind', metavar='ADDRESS',
help='bind to this address '
'(default: all interfaces)')
parser.add_argument('-d', '--directory', default=os.getcwd(),
help='serve this directory '
'(default: current directory)')
# --protocol argument was introduced in Python 3.11+
parser.add_argument('-p', '--protocol', metavar='VERSION',
default='HTTP/1.1',
help='conform to this HTTP version '
'(default: %(default)s)')
parser.add_argument('port', default=8000, type=int, nargs='?',
help='bind to this port '
'(default: %(default)s)')
args = parser.parse_args()
HTTPRequestHandler.protocol_version = args.protocol
handler_class = partial(HTTPRequestHandler, directory=args.directory)
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论