Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Removed support for node < 0.3

  • Loading branch information...
commit a2107462944a24bf39562607ed866ceee7876d80 1 parent 6684934
Felix Gnass authored May 31, 2012

Showing 1 changed file with 107 additions and 75 deletions. Show diff stats Hide diff stats

  1. 182  lib/form2json.js
182  lib/form2json.js
... ...
@@ -1,100 +1,132 @@
  1
+var qs = require('querystring')
  2
+
1 3
 /**
2 4
  * Returns the specified property of the given object. If the object has no such property,
3 5
  * the property is set to the given value.
4 6
  */
5  
-function putIfAbsent(obj, prop, value) {
6  
-	var v = obj[prop];
7  
-	if (!v) {
8  
-		v = obj[prop] = value;
9  
-	}
10  
-	return v;
  7
+function setIfAbsent(obj, prop, value) {
  8
+  var v = obj[prop]
  9
+  if (!v) v = obj[prop] = value
  10
+  return v
  11
+}
  12
+
  13
+/**
  14
+ * Pushes all values to the given array, converting numbers if necessary.
  15
+ */
  16
+function pushAll(a, values) {
  17
+  for (var i=0; i < values.length; i++) {
  18
+    var v = values[i]
  19
+    if (!isNaN(v)) v = +v
  20
+    a.push(v)
  21
+  }
11 22
 }
12 23
 
13 24
 /**
14 25
  * Returns a reduce-function that merges parameters into a target object.
15 26
  */
16 27
 function fillIn() {
17  
-	
18  
-	var dict = {};
19  
-	var resolve = function(path, prop) {
20  
-		var d = dict[path];
21  
-		if (!d) {
22  
-			d = dict[path] = {index: 0};
23  
-		}
24  
-		var i = d[prop];
25  
-		if (i === undefined) {
26  
-			i = d[prop] = d.index++;
27  
-		}
28  
-		return i;
29  
-	}; 
  28
+  var dict = {}
30 29
 
31  
-	return function self(target, param) {
32  
-		var m = /^((.*?)\]?)(?:(\[|\.)(.+))?$/.exec(param.name);
33  
-		if (m) {
34  
-			var head = m[1],
35  
-				prop = m[2],
36  
-				op = m[3],
37  
-				tail = m[4],
38  
-				nested;
  30
+  function resolve(path, prop) {
  31
+    var d = dict[path]
  32
+    if (!d) {
  33
+      d = dict[path] = {index: 0}
  34
+    }
  35
+    var i = d[prop]
  36
+    if (i === undefined) {
  37
+      i = d[prop] = d.index++
  38
+    }
  39
+    return i
  40
+  }
39 41
 
40  
-			if (target instanceof Array && isNaN(prop)) {
41  
-				prop = resolve(param.path, prop);
42  
-			}
43  
-		
44  
-			if (tail) {
45  
-				nested = putIfAbsent(target, prop, op == '[' ? [] : {});
46  
-				self(nested, {
47  
-					name: tail, 
48  
-					path: (param.path || '') + head + op,
49  
-					value: param.value
50  
-				});
51  
-			}
52  
-			else {
53  
-				if (prop === '' && target instanceof Array) {
54  
-					target.push(param.value);
55  
-				}
56  
-				else {
57  
-					target[prop] = param.value;
58  
-				}
59  
-			}
60  
-		}
61  
-		return target;
62  
-	};
  42
+  return function self(target, param) {
  43
+    var m = /^((.*?)\]?)(?:(\[|\.)(.+))?$/.exec(param.name)
  44
+    if (m) {
  45
+      var head = m[1]
  46
+        , prop = m[2]
  47
+        , op = m[3]
  48
+        , tail = m[4]
  49
+        , nested
  50
+
  51
+      if (target instanceof Array && isNaN(prop)) {
  52
+        prop = resolve(param.path, prop)
  53
+      }
  54
+
  55
+      if (tail) {
  56
+        nested = setIfAbsent(target, prop, op == '[' ? [] : {})
  57
+        self(nested, {
  58
+          name: tail,
  59
+          path: (param.path || '') + head + op,
  60
+          value: param.value
  61
+        })
  62
+      }
  63
+      else {
  64
+        if (prop === '' && target instanceof Array) {
  65
+          pushAll(target, param.value)
  66
+        }
  67
+        else {
  68
+          target[prop] = param.value
  69
+        }
  70
+      }
  71
+    }
  72
+    return target
  73
+  }
63 74
 }
64 75
 
65 76
 /**
66  
- * Splits the given key-value pair at the equals sign and returns an object holding the unescaped parts.
  77
+ * Transforms a flat object into a hierarchy using the same rules as decode().
67 78
  */
68  
-function splitPair(pair) {
69  
-	var s = pair.split('=');
70  
-	return {
71  
-		name: exports.unescape(s.shift()),
72  
-		value: exports.unescape(s.join('=')) || ''
73  
-	};
  79
+exports.transform = function(obj) {
  80
+  var pairs = []
  81
+  for (var name in obj) {
  82
+    if (obj.hasOwnProperty(name)) {
  83
+      var val = obj[name]
  84
+      if (!isNaN(val)) val = +val
  85
+      pairs.push({name: name, value: val})
  86
+    }
  87
+  }
  88
+  return pairs.reduce(fillIn(), {})
74 89
 }
75 90
 
76  
-/**
77  
- * Decodes the given x-www-form-encoded String. Refer to README.md for details.
78  
- */
  91
+var rplus = /\+/g
  92
+
79 93
 exports.decode = function(data) {
80  
-	return data.split('&').map(splitPair).reduce(fillIn(), {});
  94
+  var body = qs.parse(data)
  95
+  return exports.transform(body)
81 96
 };
82 97
 
83 98
 /**
84  
- * Transforms a flat object into a hierarchy using the same rules as decode().
  99
+ * Connect middleware that adds a `req.json` property.
  100
+ * @param flatBody If `true`, connect's default decoder for
  101
+ *  application/x-www-form-urlencoded data is overwritten with
  102
+ * `querystring.parse`. Hence `req.body` will be a *flat* object,
  103
+ *  whereas `req.json` will be nested object graph.
85 104
  */
86  
-exports.transform = function(obj) {
87  
-	var pairs = [];
88  
-	for (var name in obj) {
89  
-		if (obj.hasOwnProperty(name)) {
90  
-			pairs.push({ name: name, value: obj[name] });
91  
-		}
92  
-	}
93  
-	return pairs.reduce(fillIn(), {});
94  
-};
  105
+exports.middleware = function(flatBody) {
95 106
 
96  
-var rplus = /\+/g;
  107
+  if (flatBody) {
  108
+    require('connect').middleware.bodyDecoder.decode['application/x-www-form-urlencoded'] = qs.parse
  109
+  }
97 110
 
98  
-exports.unescape = function(s) {
99  
-	return process.binding("http_parser").urlDecode(s).replace(rplus, ' ');
100  
-};
  111
+  return function form2json(req, res, next) {
  112
+    var body;
  113
+    if (!req.json) {
  114
+      try {
  115
+        if (flatBody) {
  116
+          body = req.body
  117
+        }
  118
+        else {
  119
+          body = qs.parse(rawBody)
  120
+        }
  121
+        req.json = body ? exports.transform(body) : {}
  122
+      }
  123
+      catch (err) {
  124
+        return next(err)
  125
+      }
  126
+      next()
  127
+    }
  128
+    else {
  129
+      next()
  130
+    }
  131
+  }
  132
+}

0 notes on commit a210746

Please sign in to comment.
Something went wrong with that request. Please try again.