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.

Cache Request in scope via __new__ method

See original GitHub issue

The starting point for issues should usually be a discussion…

https://github.com/encode/starlette/discussions

Possible bugs may be raised as a “Potential Issue” discussion, feature requests may be raised as an “Ideas” discussion. We can then determine if the discussion needs to be escalated into an “Issue” or not.

This will help us ensure that the “Issues” list properly reflects ongoing or needed work on the project.


  • Initially raised as discussion #495

On consuming the body there have been lots of discussions. The root reason of this problem is that Request is initialized here and there, and the caching _body logic does not work.

In order to resolve this, @alex-oleshkevich proposed an idea to cache the Request in scope by introducing __new__ as below:

diff --git a/starlette/requests.py b/starlette/requests.py
index 66c510c..69cad4c 100644
--- a/starlette/requests.py
+++ b/starlette/requests.py
@@ -188,11 +188,22 @@ async def empty_send(message: Message) -> typing.NoReturn:
 
 
 class Request(HTTPConnection):
+    def __new__(
+        cls, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send
+    ):
+        if "request" in scope:
+            return scope["request"]
+
+        obj = object.__new__(cls)
+        scope["request"] = obj
+        return obj
+

I’ve confirmed locally this succinct notion solves the original problem and it should not take us lots of time to test.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:11 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
adriangbcommented, Jun 23, 2022

@kigawas I am sorry if closing it was a bit premature, hadn’t had my coffee yet and was just trying to keep the repo organized. Let me know if you want me to re-open it, happy to do so.

1reaction
adriangbcommented, Jun 27, 2022

Here’s a runnable example:

from typing import cast
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Route
from starlette.testclient import TestClient
from starlette.types import ASGIApp, Message, Scope, Send, Receive

async def endpoint(request: Request) -> Response:
    print(f"Endpoint got {(await request.body()).decode()}")
    return Response(status_code=200)

class RequestLengthLoggingMiddleware:
    def __init__(self, app: ASGIApp) -> None:
        self.app = app

    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        async def wrapped_rcv() -> Message:
            msg = await receive()
            if msg["type"] == "http.request":
                print(f"Middleware got {cast(bytes, msg['body']).decode()}")
            return msg

        await self.app(scope, wrapped_rcv, send)

app: ASGIApp
app = Starlette(routes=[Route("/", endpoint)])
app = ResponseLengthLoggingMiddleware(app)

client = TestClient(app)

resp = client.get("/", data=b"foo bar")
assert resp.status_code == 200

@Kludex should we add something like this to #1656 ?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cache Scope | MuleSoft Documentation
The Cache scope is for storing and reusing frequently called data. You can use a Cache scope to reduce the processing load on...
Read more >
Spring cache for a given request - Stack Overflow
SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) public CacheManager cacheManager() { return new ConcurrentMapCacheManager(); }.
Read more >
Cache.add() - Web APIs - MDN Web Docs
The add() method of the Cache interface takes a URL, retrieves it, and adds the resulting response object to the given cache.
Read more >
Cache Scope and Object Store in Mule 4 - Apisero
In Mule 4 caching can be achieved in mule using cache scope and/or object-store. Cache scope internally uses Object Store to store the...
Read more >
Cache Scope Activity for caching - Mulesy.com
Cache scope is used to store or cache the result for frequently used request. Tutorial provide the step by step configuration needed to...
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