Skip to content

Commit

Permalink
support form data in PUT requests (#1183)
Browse files Browse the repository at this point in the history
* support form data in PUT requests

* fix tests
  • Loading branch information
d-maurer committed Nov 7, 2023
1 parent fe08bae commit 5105b53
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst
5.8.7 (unreleased)
------------------

- Support form data in ``PUT`` requests (following the ``multipart`` example).
Fixes `#1182 <https://github.com/zopefoundation/Zope/issues/1182>`_.

- Separate ZODB connection information into new ZODB Connections view.

- Move the cache detail links to the individual database pages.
Expand Down
25 changes: 18 additions & 7 deletions src/ZPublisher/HTTPRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1432,19 +1432,30 @@ def __init__(self, fp, environ):
url_qs = environ.get("QUERY_STRING", "")
post_qs = ""
hl = []
content_type = environ.get("CONTENT_TYPE",
"application/x-www-form-urlencoded")
hl.append(("content-type", content_type))
content_type = environ.get("CONTENT_TYPE")
if content_type is not None:
hl.append(("content-type", content_type))
else:
content_type = ""
content_type, options = parse_options_header(content_type)
content_type = content_type.lower()
content_disposition = environ.get("CONTENT_DISPOSITION")
if content_disposition is not None:
hl.append(("content-disposition", content_disposition))
# Note: ``headers`` does not reflect the complete headers.
# Likely, it should get removed altogether and accesses be replaced
# by a lookup of the corresponding CGI environment keys.
self.headers = Headers(hl)
parts = ()
if method == "POST" \
and content_type in \
("multipart/form-data", "application/x-www-form-urlencoded"):
if method in ("POST", "PUT") \
and content_type in (
"multipart/form-data", "application/x-www-form-urlencoded",
"application/x-url-encoded",
# ``Testing`` assumes "application/x-www-form-urlencoded"
# as default content type
# We have mapped a missing content type to ``""``.
"",
):
try:
fpos = fp.tell()
except Exception:
Expand All @@ -1456,7 +1467,7 @@ def __init__(self, fp, environ):
disk_limit=FORM_DISK_LIMIT,
memfile_limit=FORM_MEMFILE_LIMIT,
charset="latin-1").parts()
elif content_type == "application/x-www-form-urlencoded":
else:
post_qs = fp.read(FORM_MEMORY_LIMIT).decode("latin-1")
if fp.read(1):
raise BadRequest("form data processing "
Expand Down
18 changes: 18 additions & 0 deletions src/ZPublisher/tests/testHTTPRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,7 @@ def test_put_with_body_limit(self):
"SERVER_NAME": "localhost",
"SERVER_PORT": "8080",
"REQUEST_METHOD": "PUT",
"CONTENT_TYPE": "application",
},
None,
)
Expand Down Expand Up @@ -1514,6 +1515,23 @@ def test_form_charset(self):
self.assertEqual(req["x"], "äöü")
self.assertEqual(req["y"], "äöü")

def test_put_with_form(self):
req_factory = self._getTargetClass()
body = b"foo=foo"
req = req_factory(
BytesIO(body),
{
"SERVER_NAME": "localhost",
"SERVER_PORT": "8080",
"REQUEST_METHOD": "PUT",
"CONTENT_TYPE": "application/x-www-form-urlencoded",
"CONTENT_LENGTH": len(body),
},
None,
)
req.processInputs()
self.assertEqual(req.form["foo"], "foo")


class TestHTTPRequestZope3Views(TestRequestViewsBase):

Expand Down

0 comments on commit 5105b53

Please sign in to comment.