aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
15.05k stars 2.01k forks source link

Trailer headers #1652

Open fafhrd91 opened 7 years ago

fafhrd91 commented 7 years ago

at the moment aiohttp drops Trailer headers. Should we provide access api?

AraHaan commented 7 years ago

I do not see a reason to not do that.

fafhrd91 commented 7 years ago

reason is how to design api.

kxepal commented 7 years ago

That would be a great feature. Suddenly, it's also has not much wide support.

As for API, I think about response.trailers property which acts as like as headers, but is only accessible when response had been completely read (empty dict or exception?). Since there could be multiple trailers, user better have to explicitly specify what he want to get from there. We can parse headers[TRAILER] in to list of hdrs to make things a little bit friendly.

The most interesting part is how to send the trailers. I can't figure anything better except to pass a dict of header: lambda which will be processes at the end of sending request payload. But, user will have to setup own generator/coroutine with all these closures since we encapsulated all the streaming within ClientRequest.write_bytes method which is not a part of frontend API. Or we can have a ClientChunkedRequest which will be more friendly for explicit data streaming.

Just a thoughts (:

fafhrd91 commented 7 years ago

I personally do not care about send part, if user wants to send trailer header he should implement chunking himself, it is easy. I am more concerned how to pass trailer data from parser.

gsauthof commented 6 years ago

FWIW, I care about both parts, client and server.

Since the StreamResponse already has enable_chunked_encoding() it would be natural to also support chunked trailer headers.

Regarding the server side API, perhaps adding an optional dictionary parameter to write_eof() wouldn't be too surprising.

asvetlov commented 6 years ago

write_trailers() looks even better :)

gsauthof commented 6 years ago

@asvetlov with a write_trailers() method you need to extend the state machine. After a call to write_trailers() only a call to write_eof() should be allowed. Also, write_trailers() and write_eof() effectively would always show up in pairs. Arguably, these are arguments in favor of an optional parameter to write_eof().

Btw, currently, I'm using this as workaround for sending headers in the chunked trailer part:

value = some_accumulated_value # e.g. a checksum
response._payload_writer.chunked = False
response._chunked = False
await response.write(b'0\r\n')
hs = multidict.CIMultiDict( [('X-foo', value)] )
headers = ''.join(['{}: {}\r\n'.format(k, v) for k, v in hs.items()])
headers = headers.encode('utf-8') + b'\r\n'
await response.write(headers)
await response.write_eof()
vegerot commented 2 months ago

I'd like this because my server is sending Server-Timing trailer that I need to read. Is there any workaround for this?