tornadoweb / tornadoweb/tornado
Getting the templated path that led to an handler
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 22.2k
- Forks
- 5.6k
- Avg merge
- 3h 42m
- Merged PRs (30d)
- 16
Description
For observability purpose in the tornado OpenTelemetry instrumentation we would like to get a templated path that led to an handler, e.g. with the following code:
class StoryHandler(RequestHandler):
def get(self, story_id):
self.write("this is story %s" % story_id)
app = Application([
url(r"/story/([0-9]+)", StoryHandler, name="story")
])
We would like to being able to build something like /story/<story_id> starting from an handler instance, but let's ignore the regexp pattern to name problem and just think on how to get the rule. ATM I've drafted the following code:
from __future__ import annotations
from typing import Any
from tornado.routing import Router
from tornado.web import RequestHandler
from tornado import httputil
# Distinguishes "keep scanning sibling rules" from "matched a branch we can't
# inspect further, so stop and report no reliable result".
_NOT_FOUND = object()
def find_matched_rule(handler: RequestHandler):
result = _find_rule(
handler.application.default_router,
handler.request,
handler.__class__,
)
return None if result is _NOT_FOUND else result
def _find_rule(router: Any, request: httputil.HTTPServerRequest, handler_class: type[RequestHandler]):
rules = getattr(router, "rules", None)
if rules is None:
# Opaque custom router; cannot inspect reliably.
return _NOT_FOUND
for rule in rules:
params = rule.matcher.match(request)
if params is None:
continue
target = getattr(rule, "target", None)
if _is_handler_target(target):
if target is handler_class:
return rule
# A different handler matched first, so Tornado would stop here too.
return _NOT_FOUND
if hasattr(target, "rules"):
nested = _find_rule(target, request, handler_class)
if nested is None:
# Nested router did not resolve anything; keep scanning siblings.
continue
return nested
if isinstance(target, Router):
# Custom nested router matched, but we cannot see inside it.
return _NOT_FOUND
# Callable / connection delegate / other terminal target.
return _NOT_FOUND
return None
def _is_handler_target(target: Any) -> bool:
return isinstance(target, type) and issubclass(target, RequestHandler)
So wondering if we're missing something or maybe we can get some help from tornado itself like a reference to the matched url in the handler. Thanks!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with tornado.routing.Router, tornado.web.RequestHandler, and httputil.HTTPServerRequest, then trace application.default_router and the rule matcher and target behavior described in the issue. Determine how a handler could reliably expose its matched route across nested and custom routers. Done means a supported way to obtain the matched rule or templated path, with behavior defined for unsupported router targets.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100