aio-libs / aiohttp

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

Multipart base64 encoding produces long line #2087

Open manuco opened 7 years ago

manuco commented 7 years ago

Long story short

When using the aiohttp.multipart module, and its MultipartWriter class, we can create multipart documents whose payload can be transfert-encoded in base64.

We use this module to retrieve some http content via aiohttp client, and stream a multipart document containing the Responses provided by the client to another processus via stdout (so we're not buffering the contents into memory, but act like a proxy).

The MultipartWriter generates base64 subdocuments without newlines. In version 0.2.1 of aiohttp, it was with multiple lines.

I know the base64 format does not define line length, but :

I think the MultipartWriter should allow us to generate base64 sub contents with newlines (potentially with an option).

Expected behaviour

When producing a multipart document with base64 tranfert encoding, the final document should not have lines longer than 78 characters (more or less).

Actual behaviour

When producing a multipart document with base64 tranfert encoding, the final document has the entire base64 subdocument on one line.

Steps to reproduce

import sys

import asyncio
import aiohttp.multipart as mp

class Writer:
    @asyncio.coroutine
    def write(self, chunk):
        sys.stdout.buffer.write(chunk)

a = mp.MultipartWriter()
a.append("i" * 200, {"Content-transfer-encoding": "base64"})
loop = asyncio.get_event_loop()

loop.run_until_complete(a.write(Writer()))

Fix

In aiohttp.multipart.MultipartPayloadWriter.write() method, the call to base64.b64encode could be replaced by base64.encodebytes which takes care of the newlines.

fafhrd91 commented 7 years ago

I think this is reasonable. would you create PR and test case?

manuco commented 7 years ago

I'll try this. No deadline for now, but I'm thinking of it.