question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Labeling / tagging routes

See original GitHub issue

Is your feature request related to a problem? Please describe. Some of my routes requires authentication and some of them don’t (such as home page). I’m currently using a middleware and hard-code URLs that requires authentication, however it would be better to have a property on routes when registering them.

@bp.on_request
async def before_request(request : Request):
    if request.route and request.route.uri in [
        "/authorize",
        "/profile/<user:str>"
    ]:
        request.ctx.token = decrypt_token(request.cookies.get("access_token"))
        # If user is not signed in, redirect user to OAuth.
        if (request.route.uri != "/authorize") and (not request.ctx.token):
            return redirect(oauth_url("ID", "/oauth_callback", request.path))
    # No need to get token for other endpoints becase other pages
    # doesn't require auth and decrypt_token() takes time.

@bp.get("/authorize")
async def authorize(request : Request):
    ...

@bp.get("/profile/<user:str>")
async def profile(request : Request, user : str):
    ...

@bp.get("/")
async def home(request : Request):
    ...

Describe the solution you’d like It can be much easier (and may look cleaner) if we have tags or labels parameter when registering the routes. (It can accept a list of enums or strings or anything). So we can access these tags in middlewares and other places. I know I can also use a decorator and inject tags to routes, but I prefer having an in-built property instead of monkey-patching the routes.

class Tags(Enum):
    BASE_AUTH = "base_auth"
    REQUIRES_AUTH = "requires_auth"

@bp.on_request
async def before_request(request : Request):
    if Tags.REQUIRES_AUTH in request.route.tags:
        request.ctx.token = decrypt_token(request.cookies.get("access_token"))
        # If user is not signed in, redirect user to OAuth.
        if (Tags.BASE_AUTH in request.route.tags) and (not request.ctx.token):
            return redirect(oauth_url("ID", "/oauth_callback", request.path))
    # No need to get token for other endpoints becase other pages
    # doesn't require auth and decrypt_token() takes time.

@bp.get("/authorize", tags = [Tags.REQUIRES_AUTH, Tags.BASE_AUTH])
async def authorize(request : Request):
    ...

@bp.get("/profile/<user:str>", tags = [Tags.REQUIRES_AUTH])
async def profile(request : Request, user : str):
    ...

@bp.get("/")
async def home(request : Request):
    ...

Additional context N/A

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
ahopkinscommented, Nov 6, 2021

Oh, I only knew request objects has ctx but I didn’t know routes has ctx too. Thanks, this is even better than tags! I haven’t seen that in docs (or I missed it - sorry).

This probably is an undocumented feature. 😬 In which case I am sorry. It exists mainly for the benefit of plugin developers, and I think it is the only instance where Sanic actually injects data into one of these objects.

So, to make it clear, I need to create a new decorator, then set ctx on routes.

It would be nice if that were the case, but I am not so sure it would be that easy. I think you would need to do something a little more “hands on”. You could do something like this:

def labelled_route(app: Sanic, *args, labels: List[str], **kwargs):
    def decorator(f):
        starting = app._future_routes
        app.route(*args, **kwargs, apply=False)(f)
        diff = starting | app._future_routes
        future_route = list(diff)[0]
        route_list = app._apply_route(future_route)
        for route in route_list:
            route.ctx.labels = labels

        return f

    return decorator


@labelled_route(app, "/", labels=["apple"])
async def handler(request: Request):
    return json(request.route.ctx.labels)

The problem is that this would not work so well with Blueprints because blueprint routes are not applied when they are declared, but instead when you register them with app.blueprint.


What I am suggesting is that we implement something like this as an API:

@app.get("/", context={"labels": ["apple"], "foo": 123})
async def handler(request: Request):
    assert request.route.ctx.labels == ["apple"]
    assert request.route.ctx.foo == 123

Since route.ctx is the only place where it is not safe to put arbitrary information into the ctx object (there is a whole different discussion about why that is), we would need to put more thought than just the above into it. But it totally makes sense to me, especially since it is not so easy otherwise to get access to the route object at definition.

1reaction
Troniccommented, Nov 7, 2021

@ahopkins See my comment on the PR, if the argument on the route decorator is named ctx_kwargs, then it suddenly becomes a lot more obvious, or at least discoverable 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to configure Route Tagging - NetworkLessons.com
You can tag routes using a route-map. I created a simple route-map called TAG with two sequence numbers: Sequence number 10 says that...
Read more >
CCNP ROUTE Tutorial and Lab: How and Why To Tag Routes -
As routes are redistributed into OSPF, we can tag them with a numeric value of our choice, and then deny values with that...
Read more >
SOLIDWORKS Routing - Adding Labels or Tags - YouTube
See more at: http://www.goengineer.com/products/solidworks/Learn about using the Routing package in SOLIDWORKS to create and represent ...
Read more >
Labelling alternative routes - Benjamin Becquet
Labels should point at parts of the routes which are non-ambiguous. ... Ambiguous labelling of routes sharing a long part.
Read more >
Labelling and grouping your Google Cloud Platform resources
For routes, tags are used to identify which instances a certain route applies to. For example, you might create a route that applies...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found