pixl-server-web 1.3.20 → 1.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -518,6 +518,26 @@ When this boolean is set to `true`, [Custom URI Handlers](#custom-uri-handlers)
518
518
  }
519
519
  ```
520
520
 
521
+ ## http_flatten_query
522
+
523
+ By default, we use the Node.js core [Query String](https://nodejs.org/api/querystring.html) module to parse query strings. This module handles duplicate query params by converting them to arrays. For example, an incoming URI such as `/something?foo=bar1&foo=bar2&name=joe` would produce the following `args.query` object:
524
+
525
+ ```js
526
+ {
527
+ "foo": ["bar1", "bar2"],
528
+ "name": "joe"
529
+ }
530
+ ```
531
+
532
+ However, if you set `http_flatten_query` to `true` in your configuration, the web server will "flatten" query string parameters, so that duplicate keys will be combined into one, with the latter prevailing. Example:
533
+
534
+ ```js
535
+ {
536
+ "foo": "bar2",
537
+ "name": "joe"
538
+ }
539
+ ```
540
+
521
541
  ## http_req_max_dump_enabled
522
542
 
523
543
  When this boolean is set to `true`, the [Request Max Dump](#request-max-dump) system is enabled. This will produce a JSON dump file when the web server is maxed out on requests.
@@ -876,6 +896,8 @@ Duplicate query params become an array. For example, an incoming URI such as `/
876
896
  }
877
897
  ```
878
898
 
899
+ See [http_flatten_query](#http_flatten_query) if you would rather the query string be flattened.
900
+
879
901
  ### args.params
880
902
 
881
903
  If the request was a HTTP POST, this will contain all the post parameters as key/value pairs. This will take one of three forms, depending on the request's `Content-Type` header:
package/lib/request.js CHANGED
@@ -175,6 +175,13 @@ module.exports = class Request {
175
175
  query = Querystring.parse( RegExp.$1 );
176
176
  }
177
177
 
178
+ // optionally flatten query (latter prevails)
179
+ if (this.config.get('http_flatten_query')) {
180
+ for (var key in query) {
181
+ if (typeof(query[key]) == 'object') query[key] = query[key].pop();
182
+ }
183
+ }
184
+
178
185
  // determine how to process request body
179
186
  var params = {};
180
187
  var files = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixl-server-web",
3
- "version": "1.3.20",
3
+ "version": "1.3.21",
4
4
  "description": "A web server component for the pixl-server framework.",
5
5
  "author": "Joseph Huckaby <jhuckaby@gmail.com>",
6
6
  "homepage": "https://github.com/jhuckaby/pixl-server-web",
package/test/test.js CHANGED
@@ -208,7 +208,7 @@ module.exports = {
208
208
  // query string
209
209
  function testQueryString(test) {
210
210
  // test simple HTTP GET request with query string
211
- request.json( 'http://127.0.0.1:3020/json?foo=bar1234&baz=bop%20pog', false,
211
+ request.json( 'http://127.0.0.1:3020/json?foo=bar1234&baz=bop%20pog&animal=frog&animal=dog', false,
212
212
  {
213
213
  headers: {
214
214
  'X-Test': "Test"
@@ -228,6 +228,12 @@ module.exports = {
228
228
  test.ok( json.query.foo == "bar1234", "Query contains correct foo key" );
229
229
  test.ok( json.query.baz == "bop pog", "Query contains correct baz key (URL encoding)" );
230
230
 
231
+ // dupes should become array by default
232
+ test.ok( typeof(json.query.animal) == 'object', "Query param animal is an object" );
233
+ test.ok( json.query.animal.length == 2, "Query param animal has length 2" );
234
+ test.ok( json.query.animal[0] === 'frog', "First animal is frog" );
235
+ test.ok( json.query.animal[1] === 'dog', "Second animal is dog" );
236
+
231
237
  // request headers will be echoed back
232
238
  test.ok( !!json.headers, "Found headers echoed in JSON response" );
233
239
  test.ok( json.headers['x-test'] == "Test", "Found Test header echoed in JSON response" );
@@ -237,6 +243,46 @@ module.exports = {
237
243
  );
238
244
  },
239
245
 
246
+ function testQueryStringFlatten(test) {
247
+ // test simple HTTP GET request with query string dupes flattened
248
+ var web = this.web_server;
249
+ web.config.set('http_flatten_query', true);
250
+
251
+ request.json( 'http://127.0.0.1:3020/json?foo=bar1234&baz=bop%20pog&animal=frog&animal=dog', false,
252
+ {
253
+ headers: {
254
+ 'X-Test': "Test"
255
+ }
256
+ },
257
+ function(err, resp, json, perf) {
258
+ test.ok( !err, "No error from PixlRequest: " + err );
259
+ test.ok( !!resp, "Got resp from PixlRequest" );
260
+ test.ok( resp.statusCode == 200, "Got 200 response: " + resp.statusCode );
261
+ test.ok( resp.headers['via'] == "WebServerTest 1.0", "Correct Via header: " + resp.headers['via'] );
262
+ test.ok( !!json, "Got JSON in response" );
263
+ test.ok( json.code == 0, "Correct code in JSON response: " + json.code );
264
+ test.ok( !!json.user, "Found user object in JSON response" );
265
+ test.ok( json.user.Name == "Joe", "Correct user name in JSON response: " + json.user.Name );
266
+
267
+ test.ok( !!json.query, "Found query object in JSON response" );
268
+ test.ok( json.query.foo == "bar1234", "Query contains correct foo key" );
269
+ test.ok( json.query.baz == "bop pog", "Query contains correct baz key (URL encoding)" );
270
+
271
+ test.ok( typeof(json.query.animal) == 'string', "Query param animal is a string" );
272
+ test.ok( json.query.animal === 'dog', "Animal is dog" );
273
+
274
+ // request headers will be echoed back
275
+ test.ok( !!json.headers, "Found headers echoed in JSON response" );
276
+ test.ok( json.headers['x-test'] == "Test", "Found Test header echoed in JSON response" );
277
+
278
+ // revert our hot config change
279
+ web.config.set('http_flatten_query', false);
280
+
281
+ test.done();
282
+ }
283
+ );
284
+ },
285
+
240
286
  // Cookies in request
241
287
  function testCookieRequest(test) {
242
288
  // test simple HTTP GET request with cookies
package/web_server.js CHANGED
@@ -60,6 +60,7 @@ module.exports = Class({
60
60
  "http_clean_headers": false,
61
61
  "http_log_socket_errors": true,
62
62
  "http_full_uri_match": false,
63
+ "http_flatten_query": false,
63
64
  "http_request_timeout": 0,
64
65
  "http_req_max_dump_enabled": false,
65
66
  "http_req_max_dump_dir": "",