I want to be able to add an instance variable to my subclass of http.server.BaseHTTPRequestHandler.
Here's my code:
from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib
class Server(BaseHTTPRequestHandler):
def __init__(self, request, client_addr, server):
super().__init__(request, client_addr, server)
self.pathobj = urllib.parse.urlparse(self.path)
def do_HEAD(self):
self.send_response(200)
def do_GET(self):
print(self.pathobj)
self.send_response(200)
self.end_headers()
def do_POST(self):
print(self.pathobj)
self.send_response(405)
self.end_headers()
def run(server_class=HTTPServer, handler_class=Server, port=8080):
server_address = ("", port)
httpd = server_class(server_address, handler_class)
print("Starting httpd on port {}...".format(port))
httpd.serve_forever()
if __name__ == "__main__":
run()
I want to be able to access the ParseResult
object returned by urllib.parse.urlparse
in each class method without needing to rewrite self.pathobj = urllib.parse.urlparse(self.path)
at the beginning of every class method.
The above code does not work -- when do_GET
or do_POST
are called it complains that 'Server' object has no attribute 'pathobj'
.
The above docs for http.server.BaseHTTPRequestHandler say:
All of the relevant information is stored in instance variables of the handler. Subclasses should not need to override or extend the
__init__()
method.
But I don't see another way to do this. Is it possible?
The docs say
The handler will parse the request and the headers, then call a method specific to the request type.
As it turns out, http.server.BaseHTTPRequestHandler
ultimately inherits from socketserver.BaseRequestHandler
, and socketserver.BaseRequestHandler.__init__()
(defined here) calls do_GET()
. So the issue is that the instance variable is actually being set after do_GET()
has already been called.
So in order to make this work, you'll need to move the self.pathobj
line above the super()
line and then rewrite it to do the parsing that BaseHTTPRequestHandler
does to construct self.path
.