aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-12-24 15:33:05 +0100
committerChristian Grothoff <christian@grothoff.org>2019-12-24 15:33:05 +0100
commitf5d59eb3a7c54cd13550ed906a67f1bff630b2c6 (patch)
tree015b7ea665c413d4932de3bcfb799f7efa7312cd /src/microhttpd
parent878c8c7e019b95aaace6a4a9edf1e584abc5ceae (diff)
downloadlibmicrohttpd-f5d59eb3a7c54cd13550ed906a67f1bff630b2c6.tar.gz
libmicrohttpd-f5d59eb3a7c54cd13550ed906a67f1bff630b2c6.zip
Given post body "a&b=1", how should MHD interpret the data?
I'm at the end of a long investigation and it's come down to that question for post_process_urlencoded() in MHD. MHD currently calls back with ("a&b", "1"). The app I'm working breaks when it doesn't receive a callback for "b". The http client in this case (that did the urlencoding) is google-http-java-client 1.23.0. The client behavior may be questionable, but MHD's behavior doesn't seem right either. Isn't there some principle, "clients should strive for conformance, servers should strive for forgiveness". I've attached a patch to MHD to add a failing test, but without a fix. As for relevant standards, the W3C[1] is not detailed enough to cover it. The WhatWG[2] is more specific and allows for empty values and even empty keys. I'd like to callout uriparser[3], another C library I've patched in as a work-around. Uriparser documents their handling of these cases well: * NULL in the value member means there was no '=' in the item text as with "?abc&def". * An empty string in the value member means there was '=' in the item as with "?abc=&def". [1] https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 [2] https://url.spec.whatwg.org/#urlencoded-parsing [3] https://uriparser.github.io/doc/api/latest/#querystrings commit aa0534af56d135e1b261d127af09c22015c1ff87 Author: Ethan Tuttle <ethan@ethantuttle.com> Date: Tue Dec 24 03:50:59 2019 -0800 urlencoding post-processor: add failing tests for keys without values
Diffstat (limited to 'src/microhttpd')
-rw-r--r--src/microhttpd/test_postprocessor.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c
index 75b5ba33..6f8ce6f5 100644
--- a/src/microhttpd/test_postprocessor.c
+++ b/src/microhttpd/test_postprocessor.c
@@ -17,13 +17,11 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20
21/** 20/**
22 * @file test_postprocessor.c 21 * @file test_postprocessor.c
23 * @brief Testcase for postprocessor 22 * @brief Testcase for postprocessor
24 * @author Christian Grothoff 23 * @author Christian Grothoff
25 */ 24 */
26
27#include "platform.h" 25#include "platform.h"
28#include "microhttpd.h" 26#include "microhttpd.h"
29#include "internal.h" 27#include "internal.h"
@@ -42,8 +40,18 @@
42 * five NULL-entries. 40 * five NULL-entries.
43 */ 41 */
44const char *want[] = { 42const char *want[] = {
43#define URL_NOVALUE1_DATA "abc&x=5"
44#define URL_NOVALUE1_START 0
45 "abc", NULL, NULL, NULL, NULL,
46 "x", NULL, NULL, NULL, "5",
47#define URL_NOVALUE1_END (URL_NOVALUE1_START + 10)
48#define URL_NOVALUE2_DATA "abc=&x=5"
49#define URL_NOVALUE2_START URL_NOVALUE1_END
50 "abc", NULL, NULL, NULL, "",
51 "x", NULL, NULL, NULL, "5",
52#define URL_NOVALUE2_END (URL_NOVALUE2_START + 10)
45#define URL_DATA "abc=def&x=5" 53#define URL_DATA "abc=def&x=5"
46#define URL_START 0 54#define URL_START URL_NOVALUE2_END
47 "abc", NULL, NULL, NULL, "def", 55 "abc", NULL, NULL, NULL, "def",
48 "x", NULL, NULL, NULL, "5", 56 "x", NULL, NULL, NULL, "5",
49#define URL_END (URL_START + 10) 57#define URL_END (URL_START + 10)
@@ -125,12 +133,14 @@ value_checker (void *cls,
125 133
126 134
127static int 135static int
128test_urlencoding (void) 136test_urlencoding_case (unsigned int want_start,
137 unsigned int want_end,
138 const char *url_data)
129{ 139{
130 struct MHD_Connection connection; 140 struct MHD_Connection connection;
131 struct MHD_HTTP_Header header; 141 struct MHD_HTTP_Header header;
132 struct MHD_PostProcessor *pp; 142 struct MHD_PostProcessor *pp;
133 unsigned int want_off = URL_START; 143 unsigned int want_off = want_start;
134 size_t i; 144 size_t i;
135 size_t delta; 145 size_t delta;
136 size_t size; 146 size_t size;
@@ -147,21 +157,34 @@ test_urlencoding (void)
147 pp = MHD_create_post_processor (&connection, 157 pp = MHD_create_post_processor (&connection,
148 1024, &value_checker, &want_off); 158 1024, &value_checker, &want_off);
149 i = 0; 159 i = 0;
150 size = strlen (URL_DATA); 160 size = strlen (url_data);
151 while (i < size) 161 while (i < size)
152 { 162 {
153 delta = 1 + MHD_random_ () % (size - i); 163 delta = 1 + MHD_random_ () % (size - i);
154 MHD_post_process (pp, &URL_DATA[i], delta); 164 MHD_post_process (pp, &url_data[i], delta);
155 i += delta; 165 i += delta;
156 } 166 }
157 MHD_destroy_post_processor (pp); 167 MHD_destroy_post_processor (pp);
158 if (want_off != URL_END) 168 if (want_off != want_end)
159 return 1; 169 return 1;
160 return 0; 170 return 0;
161} 171}
162 172
163 173
164static int 174static int
175test_urlencoding (void)
176{
177 unsigned int errorCount = 0;
178 errorCount += test_urlencoding_case (URL_START, URL_END, URL_DATA);
179 errorCount += test_urlencoding_case (URL_NOVALUE1_START, URL_NOVALUE1_END,
180 URL_NOVALUE1_DATA);
181 errorCount += test_urlencoding_case (URL_NOVALUE2_START, URL_NOVALUE2_END,
182 URL_NOVALUE2_DATA);
183 return errorCount;
184}
185
186
187static int
165test_multipart_garbage (void) 188test_multipart_garbage (void)
166{ 189{
167 struct MHD_Connection connection; 190 struct MHD_Connection connection;