Skip to content

Commit

Permalink
pocoproject#2565: HTMLForm: optional enforcement of Content-Length in…
Browse files Browse the repository at this point in the history
…stead of Chunked Transfer-Encoding
  • Loading branch information
obiltschnig committed Dec 12, 2018
1 parent 235f8d0 commit 7d6565d
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
16 changes: 13 additions & 3 deletions Net/include/Poco/Net/HTMLForm.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class Net_API HTMLForm: public NameValueCollection
/// form fields programmatically. The default limit is 100.
{
public:
enum Options
{
OPT_USE_CONTENT_LENGTH = 0x01
/// Don't use Chunked Transfer-Encoding for multipart requests.
};

HTMLForm();
/// Creates an empty HTMLForm and sets the
/// encoding to "application/x-www-form-urlencoded".
Expand Down Expand Up @@ -138,7 +144,7 @@ class Net_API HTMLForm: public NameValueCollection
/// Note that read() does not clear the form before
/// reading the new values.

void prepareSubmit(HTTPRequest& request);
void prepareSubmit(HTTPRequest& request, int options = 0);
/// Fills out the request object for submitting the form.
///
/// If the request method is GET, the encoded form is appended to the
Expand All @@ -151,7 +157,12 @@ class Net_API HTMLForm: public NameValueCollection
/// - the content transfer encoding is set to identity encoding
/// Otherwise, if the request's HTTP version is HTTP/1.1:
/// - the request's persistent connection state is left unchanged
/// - the content transfer encoding is set to chunked
/// - the content transfer encoding is set to chunked, unless
/// the OPT_USE_CONTENT_LENGTH is given in options
///
/// Note: Not using chunked transfer encoding for multipart forms
/// degrades performance, as the request content must be generated
/// twice, first to determine its size, then to actually send it.

std::streamsize calculateContentLength();
/// Calculate the content length for the form.
Expand Down Expand Up @@ -251,7 +262,6 @@ class Net_API HTMLForm: public NameValueCollection
//
// inlines
//

inline const std::string& HTMLForm::getEncoding() const
{
return _encoding;
Expand Down
6 changes: 3 additions & 3 deletions Net/src/HTMLForm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ void HTMLForm::read(const std::string& queryString)
}


void HTMLForm::prepareSubmit(HTTPRequest& request)
void HTMLForm::prepareSubmit(HTTPRequest& request, int options)
{
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
Expand All @@ -238,11 +238,11 @@ void HTMLForm::prepareSubmit(HTTPRequest& request)
request.setKeepAlive(false);
request.setChunkedTransferEncoding(false);
}
else if (_encoding != ENCODING_URL)
else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0)
{
request.setChunkedTransferEncoding(true);
}
if (!request.getChunkedTransferEncoding())
if (!request.getChunkedTransferEncoding() && !request.hasContentLength())
{
request.setContentLength(calculateContentLength());
}
Expand Down
21 changes: 21 additions & 0 deletions Net/testsuite/src/HTMLFormTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ void HTMLFormTest::testSubmit2()
HTTPRequest req("POST", "/form.cgi");
form.prepareSubmit(req);
assertTrue (req.getContentType() == HTMLForm::ENCODING_URL);
assertTrue (req.getContentLength() == 64);
}


Expand Down Expand Up @@ -338,6 +339,25 @@ void HTMLFormTest::testSubmit4()
}


void HTMLFormTest::testSubmit5()
{
HTMLForm form(HTMLForm::ENCODING_MULTIPART);
form.set("field1", "value1");
form.set("field2", "value 2");
form.set("field3", "value=3");
form.set("field4", "value&4");

HTTPRequest req("POST", "/form.cgi", HTTPMessage::HTTP_1_1);
form.prepareSubmit(req, HTMLForm::OPT_USE_CONTENT_LENGTH);
std::string expCT(HTMLForm::ENCODING_MULTIPART);
expCT.append("; boundary=\"");
expCT.append(form.boundary());
expCT.append("\"");
assertTrue (req.getContentType() == expCT);
assertTrue (req.getContentLength() == 403);
}


void HTMLFormTest::testFieldLimitUrl()
{
HTTPRequest req("GET", "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264");
Expand Down Expand Up @@ -423,6 +443,7 @@ CppUnit::Test* HTMLFormTest::suite()
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit4);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit5);
CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitUrl);
CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitMultipart);

Expand Down
1 change: 1 addition & 0 deletions Net/testsuite/src/HTMLFormTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class HTMLFormTest: public CppUnit::TestCase
void testSubmit2();
void testSubmit3();
void testSubmit4();
void testSubmit5();
void testFieldLimitUrl();
void testFieldLimitMultipart();

Expand Down

0 comments on commit 7d6565d

Please sign in to comment.