Skip to content

Allow request hooks to return a response to return immediately#150

Open
mishaschwartz wants to merge 1 commit into
bird-house:masterfrom
mishaschwartz:response-in-request-hook
Open

Allow request hooks to return a response to return immediately#150
mishaschwartz wants to merge 1 commit into
bird-house:masterfrom
mishaschwartz:response-in-request-hook

Conversation

@mishaschwartz
Copy link
Copy Markdown

This feature allows a request hook to completely skip sending the request to the upstream service and return a response immediately.

Right now, if I want to deny access to the upstream service within a request hook I can raise a (python) error which will return a 500 status response to the user. This 500 error has a generic error message and body which may or may not appropriately convey the reason for the error.

With this change I can instead return a pyramid.responses.Response object directly from the request hook. This will return the response to the user which allows me to customize the status code, body, headers, etc. This makes the response much more informative to the user.

My specific use case:

  • I have a service that contains the user's user name in the URL path (e.g. /users/<username>/some/other/resource/)
  • I want to deny access to any path that doesn't match the user's user name that is requesting the resource
    • For example I want the user named joe to be able to access paths that start with /users/joe/ but deny everyone else
  • I could create a rule in magpie that creates a resource for each user at /users/<username> for each user that gets create, I could even try to automate this with cowbird
  • However, I could also create a hook that checks the user against the path and returns a 401 response (which is what I've opted for here)

@fmigneault
Copy link
Copy Markdown
Member

@mishaschwartz
Not sure if I'm misinterpreting, but it seems exactly to be what https://pavics-magpie.readthedocs.io/en/latest/configuration.html#service-hooks is for?

As a few examples, https://github.com/bird-house/birdhouse-deploy/blob/master/birdhouse/components/weaver/config/magpie/weaver_hooks.py.template uses them to modify the request/response contents (and even create extra permissions if needed) based on the identified user.

From the perspective of Twitcher, technically, it does not know "user" and it is not its role. Twitcher enforces the decision (PEP). Magpie makes the decision (PDP) since it knows the resources.

@fmigneault
Copy link
Copy Markdown
Member

@mishaschwartz
OK. I think I understand the use case slightly better after re-reading.
Since the hooks are invoked as (pre-request) -> [request] -> (post-response),
you want to skip the [request] -> (post-response) entirely?

I would like to consider other things just to make sure we don't maintain many ways to do similar procedures.

What does the /users/<username> endpoint actually points to?
If all -> [requests] -> ... are bypassed with an immediate Response, why is the purpose of the endpoint? It couldn't be a basic Nginx location /... {return 200 ""}; ?

Otherwise, wouldn't there be a way to invoke the auth_request /twitcher/ows/proxy/verify/... to do just the check portion of user access (which could have a request_hook call), and then the rest of the Nginx config does whatever else it needs?

@mishaschwartz
Copy link
Copy Markdown
Author

Not sure if I'm misinterpreting, but it seems exactly to be what https://pavics-magpie.readthedocs.io/en/latest/configuration.html#service-hooks is for?

Yes I'm setting this up as a service hook. But the hooks are invoked by the owsproxy_view function where I've made the change here.

At the point where owsproxy_view is called, the request argument does contain a reference to the Magpie user so you definitely can access user information within a hook.

If all -> [requests] -> ... are bypassed with an immediate Response, why is the purpose of the endpoint?

There's conditional logic there... some calls will return a request and then the request will get passed to the upstream service and others will return a response immediately.

Otherwise, wouldn't there be a way to invoke the auth_request /twitcher/ows/proxy/verify/... to do just the check portion of user access (which could have a request_hook call),

The hooks aren't actually invoked for the verify calls right now. If you think that's a better solution then I'm happy to move this logic to the verify endpoint instead.

@mishaschwartz mishaschwartz mentioned this pull request May 22, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants