mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-25 18:22:59 +02:00 
			
		
		
		
	#2565: HTMLForm: optional enforcement of Content-Length instead of Chunked Transfer-Encoding
This commit is contained in:
		| @@ -46,6 +46,12 @@ class Net_API HTMLForm: public NameValueCollection | |||||||
| 	/// form fields programmatically. The default limit is 100. | 	/// form fields programmatically. The default limit is 100. | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | 	enum Options | ||||||
|  | 	{ | ||||||
|  | 		OPT_USE_CONTENT_LENGTH = 0x01 | ||||||
|  | 			/// Don't use Chunked Transfer-Encoding for multipart requests. | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	HTMLForm(); | 	HTMLForm(); | ||||||
| 		/// Creates an empty HTMLForm and sets the | 		/// Creates an empty HTMLForm and sets the | ||||||
| 		/// encoding to "application/x-www-form-urlencoded". | 		/// encoding to "application/x-www-form-urlencoded". | ||||||
| @@ -137,7 +143,7 @@ public: | |||||||
| 		/// Note that read() does not clear the form before | 		/// Note that read() does not clear the form before | ||||||
| 		/// reading the new values. | 		/// reading the new values. | ||||||
|  |  | ||||||
| 	void prepareSubmit(HTTPRequest& request); | 	void prepareSubmit(HTTPRequest& request, int options = 0); | ||||||
| 		/// Fills out the request object for submitting the form. | 		/// Fills out the request object for submitting the form. | ||||||
| 		/// | 		/// | ||||||
| 		/// If the request method is GET, the encoded form is appended to the | 		/// If the request method is GET, the encoded form is appended to the | ||||||
| @@ -150,7 +156,12 @@ public: | |||||||
| 		///    - the content transfer encoding is set to identity encoding | 		///    - the content transfer encoding is set to identity encoding | ||||||
| 		/// Otherwise, if the request's HTTP version is HTTP/1.1: | 		/// Otherwise, if the request's HTTP version is HTTP/1.1: | ||||||
| 		///    - the request's persistent connection state is left unchanged | 		///    - 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(); | 	std::streamsize calculateContentLength(); | ||||||
| 		/// Calculate the content length for the form. | 		/// Calculate the content length for the form. | ||||||
|   | |||||||
| @@ -203,7 +203,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) | 	if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) | ||||||
| 	{ | 	{ | ||||||
| @@ -229,11 +229,11 @@ void HTMLForm::prepareSubmit(HTTPRequest& request) | |||||||
| 			request.setKeepAlive(false); | 			request.setKeepAlive(false); | ||||||
| 			request.setChunkedTransferEncoding(false); | 			request.setChunkedTransferEncoding(false); | ||||||
| 		} | 		} | ||||||
| 		else if (_encoding != ENCODING_URL) | 		else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0) | ||||||
| 		{ | 		{ | ||||||
| 			request.setChunkedTransferEncoding(true); | 			request.setChunkedTransferEncoding(true); | ||||||
| 		} | 		} | ||||||
| 		if (!request.getChunkedTransferEncoding()) | 		if (!request.getChunkedTransferEncoding() && !request.hasContentLength()) | ||||||
|  		{ |  		{ | ||||||
|  			request.setContentLength(calculateContentLength()); |  			request.setContentLength(calculateContentLength()); | ||||||
|  		} |  		} | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
| #include "Poco/Net/NetException.h" | #include "Poco/Net/NetException.h" | ||||||
| #include <sstream> | #include <sstream> | ||||||
|  |  | ||||||
|  | #include <iostream> | ||||||
|  |  | ||||||
| using Poco::Net::HTMLForm; | using Poco::Net::HTMLForm; | ||||||
| using Poco::Net::PartSource; | using Poco::Net::PartSource; | ||||||
| @@ -294,6 +295,7 @@ void HTMLFormTest::testSubmit2() | |||||||
| 	HTTPRequest req("POST", "/form.cgi"); | 	HTTPRequest req("POST", "/form.cgi"); | ||||||
| 	form.prepareSubmit(req); | 	form.prepareSubmit(req); | ||||||
| 	assertTrue (req.getContentType() == HTMLForm::ENCODING_URL); | 	assertTrue (req.getContentType() == HTMLForm::ENCODING_URL); | ||||||
|  | 	assertTrue (req.getContentLength() == 64); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -331,6 +333,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() | void HTMLFormTest::testFieldLimitUrl() | ||||||
| { | { | ||||||
| 	HTTPRequest req("GET", "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); | 	HTTPRequest req("GET", "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); | ||||||
| @@ -416,6 +437,7 @@ CppUnit::Test* HTMLFormTest::suite() | |||||||
| 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); | 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); | ||||||
| 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3); | 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3); | ||||||
| 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit4); | 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit4); | ||||||
|  | 	CppUnit_addTest(pSuite, HTMLFormTest, testSubmit5); | ||||||
| 	CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitUrl); | 	CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitUrl); | ||||||
| 	CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitMultipart); | 	CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitMultipart); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ public: | |||||||
| 	void testSubmit2(); | 	void testSubmit2(); | ||||||
| 	void testSubmit3(); | 	void testSubmit3(); | ||||||
| 	void testSubmit4(); | 	void testSubmit4(); | ||||||
|  | 	void testSubmit5(); | ||||||
| 	void testFieldLimitUrl(); | 	void testFieldLimitUrl(); | ||||||
| 	void testFieldLimitMultipart(); | 	void testFieldLimitMultipart(); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Günter Obiltschnig
					Günter Obiltschnig