sanic-org / sanic

Accelerate your web app development | Build fast. Run fast.

Home Page:https://sanic.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rewrite request and re-route

Tronic opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe.

Web servers such as Apache, Nginx and Caddy make heavy use of rewrites, which are essentially internal redirects. Rather than ask the client do another request some place else (redirect), the server while handling a request itself determines a new location and handles it internally, and the client doesn't see any of this but gets a response from the rewritten request.

Typically the path of the request is altered in a redirect, although other changes are also possible.

I am seeing use for this at least within Sanic's own static files handler, that may need rewrite to index.html after determining the target was a directory, and then re-enter itself (rather than bail out by simple return file(path / "index.html") that lacks the features of the normal static file handler. But this is in general a powerful tool for implementing some odd flows.

Describe the solution you'd like

In a handler or middleware one could

return sanic.response.rewrite(request, url="/new/path", headers=...)

After this Sanic would re-run routing to find a matching handler and restart as if it were a new request.

Alternatively this could be a request accessor: (I think I prefer this)

return request.rewrite(**changes)

Additional context

Partially read body, or streaming if body has already been consumed are hard to support. Presumably the connection handling (http1.py etc) keep track of request body and response status even if the Request object is altered, making this less of an issue (even in presence of incorrect content-length header).

Probably needs to keep a count of rewrites per request to avoid accidental infinite loops.

(I think I prefer this)

I would agree. The response module seems more like a place for creating response objects which is not really what this proposal is doing. My initial impression would be to raise a RewriteException and catch that inside the app's handle_request, swap out the path on a new Request object and call handle_request again.