python - 将 BaseHTTPRequestHandler 与 UnixStreamServer 一起使用会导致异常
python - using BaseHTTPRequestHandler with UnixStreamServer causes exception
我正在尝试创建一个绑定到 Unix 域套接字的基本 HTTP 服务器,但是将 BaseHTTPRequestHandler 子类与 UnixStreamServer 一起使用会创建一个异常,表明它们无法协同工作。
玩具server.py:
from SocketServer import UnixStreamServer
from BaseHTTPServer import BaseHTTPRequestHandler
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.end_headers()
self.wfile.write("Hi!")
server = UnixStreamServer('./mysocket.sock', MyHandler)
server.serve_forever()
然后我发送一个带有 curl --unix-socket ./mysocket.sock http:/hello
的请求,这导致服务器出现以下异常(使用 Python 2.7.11):
Exception happened during processing of request from
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 652, in __init__
self.handle()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
method()
File "server.py", line 6, in do_GET
self.send_response(200)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 385, in send_response
self.log_request(code)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 422, in log_request
self.requestline, str(code), str(size))
File "/usr/lib/python2.7/BaseHTTPServer.py", line 456, in log_message
(self.client_address[0],
IndexError: string index out of range
我做了一些挖掘,问题与 sock.accept()
returns 空字符串作为地址这一事实有关,大概是因为 UDS 调用没有客户端地址的概念。然而,BaseHTTPRequestHandler 期望一个用于日志记录(可能还有其他事情)
有没有一种方法可以解决这个问题,而不涉及猴子补丁或通过这个小改动重新实现 BaseHTTPServer? BaseHTTPRequestHandler 甚至打算与 UnixDataStream 一起使用吗? Python?
中关于轻量级 UDS HTTP 服务器的更好建议
谢谢!
我结束了 UnixStreamServer 的子类化并覆盖了 get_request(这是打算被覆盖的 TCPServer 方法之一):
class UnixHTTPServer(UnixStreamServer):
def get_request(self):
request, client_address = self.socket.accept()
# BaseHTTPRequestHandler expects a tuple with the client address at index
# 0, so we fake one
if len(client_address) == 0:
client_address = (self.server_address,)
return (request, client_address)
(注意 self.server_address 给出了用于 UDS 的文件描述符的路径)
这不是最干净的解决方案,但也不是最骇人听闻的解决方案。
您可以将 BaseHTTPRequestHandler 与 HTTPServer 一起使用。
import os, socket, BaseHTTPServer
class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send(200,'Success')
def do_POST(self):
size = int(self.headers.get('Content-Length',0))
body = self.rfile.read(size)
self.send(200,'Success')
def send(self,code,reply):
self.client_address=('',) # avoid exception in BaseHTTPServer.py log_message()
self.send_response(code)
self.end_headers()
self.wfile.write(reply)
sock_file = 'socket'
try: os.remove(sock_file)
except OSError: pass
sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
sock.bind(sock_file)
sock.listen(0)
server = BaseHTTPServer.HTTPServer(sock_file,HTTPHandler,False)
server.socket = sock
server.serve_forever()
sock.shutdown(socket.SHUT_RDWR)
sock.close()
os.remove(sock_file)
我正在尝试创建一个绑定到 Unix 域套接字的基本 HTTP 服务器,但是将 BaseHTTPRequestHandler 子类与 UnixStreamServer 一起使用会创建一个异常,表明它们无法协同工作。
玩具server.py:
from SocketServer import UnixStreamServer
from BaseHTTPServer import BaseHTTPRequestHandler
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.end_headers()
self.wfile.write("Hi!")
server = UnixStreamServer('./mysocket.sock', MyHandler)
server.serve_forever()
然后我发送一个带有 curl --unix-socket ./mysocket.sock http:/hello
的请求,这导致服务器出现以下异常(使用 Python 2.7.11):
Exception happened during processing of request from
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 652, in __init__
self.handle()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
method()
File "server.py", line 6, in do_GET
self.send_response(200)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 385, in send_response
self.log_request(code)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 422, in log_request
self.requestline, str(code), str(size))
File "/usr/lib/python2.7/BaseHTTPServer.py", line 456, in log_message
(self.client_address[0],
IndexError: string index out of range
我做了一些挖掘,问题与 sock.accept()
returns 空字符串作为地址这一事实有关,大概是因为 UDS 调用没有客户端地址的概念。然而,BaseHTTPRequestHandler 期望一个用于日志记录(可能还有其他事情)
有没有一种方法可以解决这个问题,而不涉及猴子补丁或通过这个小改动重新实现 BaseHTTPServer? BaseHTTPRequestHandler 甚至打算与 UnixDataStream 一起使用吗? Python?
中关于轻量级 UDS HTTP 服务器的更好建议谢谢!
我结束了 UnixStreamServer 的子类化并覆盖了 get_request(这是打算被覆盖的 TCPServer 方法之一):
class UnixHTTPServer(UnixStreamServer):
def get_request(self):
request, client_address = self.socket.accept()
# BaseHTTPRequestHandler expects a tuple with the client address at index
# 0, so we fake one
if len(client_address) == 0:
client_address = (self.server_address,)
return (request, client_address)
(注意 self.server_address 给出了用于 UDS 的文件描述符的路径)
这不是最干净的解决方案,但也不是最骇人听闻的解决方案。
您可以将 BaseHTTPRequestHandler 与 HTTPServer 一起使用。
import os, socket, BaseHTTPServer
class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send(200,'Success')
def do_POST(self):
size = int(self.headers.get('Content-Length',0))
body = self.rfile.read(size)
self.send(200,'Success')
def send(self,code,reply):
self.client_address=('',) # avoid exception in BaseHTTPServer.py log_message()
self.send_response(code)
self.end_headers()
self.wfile.write(reply)
sock_file = 'socket'
try: os.remove(sock_file)
except OSError: pass
sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
sock.bind(sock_file)
sock.listen(0)
server = BaseHTTPServer.HTTPServer(sock_file,HTTPHandler,False)
server.socket = sock
server.serve_forever()
sock.shutdown(socket.SHUT_RDWR)
sock.close()
os.remove(sock_file)