Skip to content

Commit

Permalink
Form data processed (#4351)
Browse files Browse the repository at this point in the history
  • Loading branch information
AtomsForPeace authored and asvetlov committed Oct 16, 2020
1 parent b4a5feb commit accabde
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGES/4345.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Raise ClientPayloadError if FormData re-processed.
4 changes: 4 additions & 0 deletions aiohttp/formdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def __init__(self, fields:
self._writer = multipart.MultipartWriter('form-data')
self._fields = [] # type: List[Any]
self._is_multipart = False
self._is_processed = False
self._quote_fields = quote_fields
self._charset = charset

Expand Down Expand Up @@ -115,6 +116,8 @@ def _gen_form_urlencoded(self) -> payload.BytesPayload:

def _gen_form_data(self) -> multipart.MultipartWriter:
"""Encode a list of fields using the multipart/form-data MIME format"""
if self._is_processed:
raise RuntimeError('Form data has been processed already')
for dispparams, headers, value in self._fields:
try:
if hdrs.CONTENT_TYPE in headers:
Expand All @@ -141,6 +144,7 @@ def _gen_form_data(self) -> multipart.MultipartWriter:

self._writer.append_payload(part)

self._is_processed = True
return self._writer

def __call__(self) -> Payload:
Expand Down
15 changes: 14 additions & 1 deletion tests/test_formdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from aiohttp.formdata import FormData
from aiohttp import ClientSession, FormData


@pytest.fixture
Expand Down Expand Up @@ -86,3 +86,16 @@ async def test_formdata_field_name_is_not_quoted(buf, writer) -> None:
payload = form()
await payload.write(writer)
assert b'name="emails[]"' in buf


async def test_mark_formdata_as_processed() -> None:
async with ClientSession() as session:
url = "http://httpbin.org/anything"
data = FormData()
data.add_field("test", "test_value", content_type="application/json")

await session.post(url, data=data)
assert len(data._writer._parts) == 1

with pytest.raises(RuntimeError):
await session.post(url, data=data)
21 changes: 10 additions & 11 deletions tests/test_web_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ def fname(here):
return here / 'conftest.py'


def new_dummy_form():
form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')
return form


async def test_simple_get(aiohttp_client) -> None:

async def handler(request):
Expand Down Expand Up @@ -513,15 +520,11 @@ async def expect_handler(request):
if request.version == HttpVersion11:
await request.writer.write(b"HTTP/1.1 100 Continue\r\n\r\n")

form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')

app = web.Application()
app.router.add_post('/', handler, expect_handler=expect_handler)
client = await aiohttp_client(app)

resp = await client.post('/', data=form, expect100=True)
resp = await client.post('/', data=new_dummy_form(), expect100=True)
assert 200 == resp.status
assert expect_received

Expand All @@ -540,20 +543,16 @@ async def expect_handler(request):

await request.writer.write(b"HTTP/1.1 100 Continue\r\n\r\n")

form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')

app = web.Application()
app.router.add_post('/', handler, expect_handler=expect_handler)
client = await aiohttp_client(app)

auth_err = False
resp = await client.post('/', data=form, expect100=True)
resp = await client.post('/', data=new_dummy_form(), expect100=True)
assert 200 == resp.status

auth_err = True
resp = await client.post('/', data=form, expect100=True)
resp = await client.post('/', data=new_dummy_form(), expect100=True)
assert 403 == resp.status


Expand Down

0 comments on commit accabde

Please sign in to comment.