Fix error when logging incomplete requests

If a connection is lost before a request is read from Request, Twisted
sets `method` (and `uri`) attributes to dummy values. These dummy values
have incorrect types (i.e. they're not bytes), and so things like
`__repr__` would raise an exception.

To fix this we had a helper method to return the method with a
consistent type.
pull/3990/head
Erik Johnston 2018-10-02 11:49:39 +01:00
parent 8c41b0ca66
commit 334e075dd8
1 changed files with 21 additions and 6 deletions

View File

@ -75,14 +75,14 @@ class SynapseRequest(Request):
return '<%s at 0x%x method=%r uri=%r clientproto=%r site=%r>' % ( return '<%s at 0x%x method=%r uri=%r clientproto=%r site=%r>' % (
self.__class__.__name__, self.__class__.__name__,
id(self), id(self),
self.method.decode('ascii', errors='replace'), self.get_method(),
self.get_redacted_uri(), self.get_redacted_uri(),
self.clientproto.decode('ascii', errors='replace'), self.clientproto.decode('ascii', errors='replace'),
self.site.site_tag, self.site.site_tag,
) )
def get_request_id(self): def get_request_id(self):
return "%s-%i" % (self.method.decode('ascii'), self.request_seq) return "%s-%i" % (self.get_method(), self.request_seq)
def get_redacted_uri(self): def get_redacted_uri(self):
uri = self.uri uri = self.uri
@ -90,6 +90,21 @@ class SynapseRequest(Request):
uri = self.uri.decode('ascii') uri = self.uri.decode('ascii')
return redact_uri(uri) return redact_uri(uri)
def get_method(self):
"""Gets the method associated with the request (or placeholder if not
method has yet been received).
Note: This is necessary as the placeholder value in twisted is str
rather than bytes, so we need to sanitise `self.method`.
Returns:
str
"""
method = self.method
if isinstance(method, bytes):
method = self.method.decode('ascii')
return method
def get_user_agent(self): def get_user_agent(self):
return self.requestHeaders.getRawHeaders(b"User-Agent", [None])[-1] return self.requestHeaders.getRawHeaders(b"User-Agent", [None])[-1]
@ -119,7 +134,7 @@ class SynapseRequest(Request):
# dispatching to the handler, so that the handler # dispatching to the handler, so that the handler
# can update the servlet name in the request # can update the servlet name in the request
# metrics # metrics
requests_counter.labels(self.method.decode('ascii'), requests_counter.labels(self.get_method(),
self.request_metrics.name).inc() self.request_metrics.name).inc()
@contextlib.contextmanager @contextlib.contextmanager
@ -207,14 +222,14 @@ class SynapseRequest(Request):
self.start_time = time.time() self.start_time = time.time()
self.request_metrics = RequestMetrics() self.request_metrics = RequestMetrics()
self.request_metrics.start( self.request_metrics.start(
self.start_time, name=servlet_name, method=self.method.decode('ascii'), self.start_time, name=servlet_name, method=self.get_method(),
) )
self.site.access_logger.info( self.site.access_logger.info(
"%s - %s - Received request: %s %s", "%s - %s - Received request: %s %s",
self.getClientIP(), self.getClientIP(),
self.site.site_tag, self.site.site_tag,
self.method.decode('ascii'), self.get_method(),
self.get_redacted_uri() self.get_redacted_uri()
) )
@ -280,7 +295,7 @@ class SynapseRequest(Request):
int(usage.db_txn_count), int(usage.db_txn_count),
self.sentLength, self.sentLength,
code, code,
self.method.decode('ascii'), self.get_method(),
self.get_redacted_uri(), self.get_redacted_uri(),
self.clientproto.decode('ascii', errors='replace'), self.clientproto.decode('ascii', errors='replace'),
user_agent, user_agent,