aiohttp icon indicating copy to clipboard operation
aiohttp copied to clipboard

Give raw string bytes in socket message instead of string

Open projects2080 opened this issue 1 month ago • 15 comments

Is your feature request related to a problem?

For very high performance websocket clients it is sometimes not desirable to automatically convert bytes to string, even if the server sends as string. It's unnecessary overhead when using high performance json parsing like orjson which can handle bytes faster.

Describe the solution you'd like

A flag that allows me to opt in to receiving bytes of string instead of actual python string.

Describe alternatives you've considered

Switch to synchronous websocket client (already supports this).

Related component

Client

Additional context

No response

Code of Conduct

  • [x] I agree to follow the aio-libs Code of Conduct

projects2080 avatar Nov 16 '25 20:11 projects2080

Look at how aioshelly implements this. Let me know if you were thinking something else

bdraco avatar Nov 16 '25 20:11 bdraco

@bdraco sorry I can't trace through that library at the moment to understand the approach.

I was thinking in session.ws_connect have a flag (not sure what to call it, maybe str_bytes=True) and if so either give the string bytes directly with WSMsgType.TEXT (or maybe more sensible to use WSMsgType.BINARY)

projects2080 avatar Nov 16 '25 20:11 projects2080

Look at how aioshelly implements this. Let me know if you were thinking something else

Isn't that just relying on orjson working with str? As far as I can see, decoding to str is not optional currently: https://github.com/aio-libs/aiohttp/blob/056d9297b2cb96c83466a3eaac3055acd9432229/aiohttp/_websocket/reader_py.py#L272-L274

Dreamsorcerer avatar Nov 16 '25 20:11 Dreamsorcerer

https://github.com/home-assistant-libs/aioshelly/pull/713/files

But I just realized you care about the incoming not the outgoing

bdraco avatar Nov 16 '25 21:11 bdraco

I was thinking in session.ws_connect have a flag (not sure what to call it, maybe str_bytes=True) and if so either give the string bytes directly with WSMsgType.TEXT (or maybe more sensible to use WSMsgType.BINARY)

You'd probably still want WSMsgType.TEXT since it has different semantic meaning than WSMsgType.BINARY.

It gets a bit messy because WSMessageText than can be str | bytes. Maybe we end up with WSMessageEncodedText but not sure how to handle that in 3.x.

I can see why you want it though as other libraries and yes, aioshelly have the same issue with the needless decode overhead that orjson will do for you.

bdraco avatar Nov 16 '25 21:11 bdraco

It gets a bit messy because WSMessageText than can be str | bytes. Maybe we end up with WSMessageEncodedText but not sure how to handle that in 3.x.

Not sure how to handle that in any version. We should know whether it's str or bytes, so we probably need 2 types and need to figure out a way for the typing information to know which of the 2 message types we should be receiving.

I suspect that'll be fairly complex to figure out.

Dreamsorcerer avatar Nov 16 '25 23:11 Dreamsorcerer

e.g. ClientWebSocketResponse may need to become Generic depending on the parameter, so that .receive() can have 2 different unions for the return type. Same for web side.

Dreamsorcerer avatar Nov 17 '25 00:11 Dreamsorcerer

Managed to work it out. The actual change is about 7 lines.. and than another 100+ lines of typing :(

bdraco avatar Nov 17 '25 18:11 bdraco

Without Unpack we have to write everything for ws_connect out for both

bdraco avatar Nov 17 '25 18:11 bdraco

and we need Self as well to properly type it.

bdraco avatar Nov 17 '25 18:11 bdraco

I gave up on the typing and closed https://github.com/aio-libs/aiohttp/pull/11764. It doesn't seem like we should add hundreds of lines of typing just to support this change

bdraco avatar Nov 17 '25 18:11 bdraco

Another option would be to add the option to receive and a new api to receive_text_bytes

bdraco avatar Nov 17 '25 18:11 bdraco

alternate approach which doesn't try to make it a Generic because that ballooned into something awful

https://github.com/aio-libs/aiohttp/pull/11765

bdraco avatar Nov 17 '25 18:11 bdraco

@bdraco you are awesome for looking at this

does that #11765 seem like it will make it in eventually?

projects2080 avatar Nov 18 '25 20:11 projects2080

TBH, I'm not sure if we want to go with https://github.com/aio-libs/aiohttp/pull/11764 or https://github.com/aio-libs/aiohttp/pull/11765.

11764 got very large and is likely to be another 300 lines larger to fully finish it. Its about to get very busy for me as I wrap up the end of year items. I'm hoping to have some time during the end of year holiday to finish it up.

bdraco avatar Nov 19 '25 22:11 bdraco

@projects2080 can you give https://github.com/aio-libs/aiohttp/pull/11764 a try?

bdraco avatar Dec 12 '25 22:12 bdraco

hi @bdraco on holiday atm, will try it soon, thank you

projects2080 avatar Dec 15 '25 15:12 projects2080