#Request in request handler not updated

1 messages · Page 1 of 1 (latest)

toxic socket
#

Hi,
I'm implementing a basic REST API application using litestar that is served by hypercorn (I need HTTP2 support).
To ease explaination of my issue, I added in my code a straightforward route handler to manage a POST on /echo. The handler replies with the content of the request body.

I have a strange behavior where the server replies always to any requests with the body of the first request sent. In the client side, I send a counter starting at 0. So in my example, the print always outputs "{'test': 0}" even if the request contains something else. It seems that the handler is not updated with the latest request.

For the sake of completeness, my client establishes a connection with my server and use the same connection to send requests.

Information:
Litestar: 2.14.0
Hypercorn: 0.17.3

Thanks for your help

stray gustBOT
#
Notes for Data in request handler not updated
At your assistance

@toxic socket

No Response?

If no response in a reasonable time, ping @Member.

Closing

To close, type !solve or byte solve.

MCVE

Please include an MCVE so that we can reproduce your issue locally.

toxic socket
#

Request in request handler not updated

rough gull
#

You will need to supply some code

#

We can't really deduce anything from what you've shared so far

#

But I can say that your handler has several issues:

  1. It's annotated as returning None but actually returns data
  2. You're using request.json() when you should just be accessing the body via the body kwargs
jolly valve
stiff swiftBOT
#

litestar/connection/base.py line 89

self._connection_state = ScopeState.from_scope(scope)

litestar/connection/request.py lines 135 to 136

if (json_ := self._connection_state.json) is not Empty:
    self._json = json_
toxic socket
#

@jolly valve so what should I do to fix it ?

#

@rough gull my code is quite simple

app/main.py

from litestar import Litestar, post, Request
from pydantic import BaseModel

class EchoBody(BaseModel):
    counter: int

@post('/echo')
async def echo_req(data: EchoBody) -> EchoBody:
      print(data)
      return data

app = Litestar(route_handlers=[echo_req], debug=True)

main.py

import asyncio

from hypercorn.asyncio import serve
from hypercorn.config import Config

from app.main import app

config = Config()
config.bind = ["0.0.0.0:8080"]
config.alpn_protocols = ["h2"]
config.keep_alive_timeout = 260

asyncio.run(serve(app, config))
jolly valve
#

dont use hypercorn until it's decided if its a hypercorn and/or litestar issue and gets fixed

toxic socket
#

What can I use instead that fullfils the requirements to support HTTP2

jolly valve
#

you could try granian, i think that supports http2, or just put a reverse proxy in front of it

toxic socket
#

Will I be notified here when it will be decided that’s a bug from hypercorn or litestar.

I tried the same setup with fastAPI, didn’t get any issue

toxic socket
thick chasm
#

we've seen some weirdness with hypercorn. You are going to get better performance from granian anyway

rough gull
jolly valve
#

yet it somehow still gets the old json content?

rough gull
stiff swiftBOT
#

src/hypercorn/protocol/http_stream.py line 87

self.scope = {
jolly valve
#

it's weird

rough gull
#

Does it go away if you don't use request.json()?

#

And just use data: dict[str, Any]?

jolly valve
#

nope

rough gull
#

Okay, good

#

I think this is likely an issue with hypercorn then. But I'll investigate

jolly valve
#

once there's a bigger gap between requests it doesnt seem to happen, but i don't see how reusing a socket would lead to this

stiff swiftBOT
#

src/hypercorn/protocol/http_stream.py line 100

"state": event.state,
rough gull
#

It is reusing some state

#

Which we are using to store per-request data

stiff swiftBOT
#

src/hypercorn/protocol/h2.py line 88

connection_state: ConnectionState,
stiff swiftBOT
#

src/hypercorn/asyncio/tcp_server.py line 63

ConnectionState(self.state.copy()),
rough gull
#

Which is being copied here, but only once per connection

#

Hmm. Seems like the spec is a bit vague there:

A copy of the namespace passed into the lifespan corresponding to this request.

#

That could also be interpreted as "copy the state of the lifespan once and pass it to every scope"

toxic socket
#

Thank both of you for your inputs.

fading shadow
stiff swiftBOT
#

uvicorn/protocols/http/h11_impl.py lines 195 to 214

elif isinstance(event, h11.Request):
    self.headers = [(key.lower(), value) for key, value in event.headers]
    raw_path, _, query_string = event.target.partition(b"?")
    path = unquote(raw_path.decode("ascii"))
    full_path = self.root_path + path
    full_raw_path = self.root_path.encode("ascii") + raw_path
    self.scope = {
        "type": "http",
        "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"},
        "http_version": event.http_version.decode("ascii"),
        "server": self.server,
        "client": self.client,
        "scheme": self.scheme,  # type: ignore[typeddict-item]
        "method": event.method.decode("ascii"),
        "root_path": self.root_path,
        "path": full_path,
        "raw_path": full_raw_path,
        "query_string": query_string,
        "headers": self.headers,
        "state": self.app_state.copy(),
fading shadow
#

ok it's http2, so three might be something I dont get connection vs request

#

might be interesting to check if their http1 implementation suffers the same

#

the whole spec names is confusing anyways, too many scope and state for very different things

rough gull
#

Yeah. It's quite ambiguous in a lot of places 😬

rough gull
#

Hah! Yes, it does!

fading shadow
#

stll dont get what connection means vs request in hypercorn's context

rough gull
#

I think the connection is really just a TCP conn?

#

For multiplexing

thick chasm
stiff swiftBOT
rough gull
#

Nah. I'm 99% certain it's the stuff I've described earlier. I'll see if I can come up with a patch for hypercorn

rough gull
rough gull
rough gull
#

@toxic socket keep an eye out on these, as they should fix your issues