diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 00000000..ab2bf802 --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 6301b6ab..fa54699e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Body Parser -![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev-red.svg) +![version 1.0.0-beta](https://img.shields.io/badge/version-1.0.0--beta-blue.svg) **NOT YET PRODUCTION READY** -Parse request bodies and query strings in Dart. +Parse request bodies and query strings in Dart. No external dependencies required. ### Contents diff --git a/Test Results - Run_All_Tests.html b/Test Results - Run_All_Tests.html index 1cac1124..a7f4b43e 100644 --- a/Test Results - Run_All_Tests.html +++ b/Test Results - Run_All_Tests.html @@ -572,8 +572,8 @@ jQuery.cookie = function(name, value, options) {
diff --git a/lib/body_parser.dart b/lib/body_parser.dart index 80e2914c..f2e61274 100644 --- a/lib/body_parser.dart +++ b/lib/body_parser.dart @@ -4,7 +4,6 @@ library body_parser; import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:json_god/json_god.dart'; /// A representation of data from an incoming request. class BodyParseResult { @@ -47,22 +46,51 @@ Future parseBody(HttpRequest request) async { /// /// Whichever map you provide will be automatically populated from the urlencoded body string you provide. buildMapFromUri(Map map, String body) { - God god = new God(); + RegExp parseArray = new RegExp(r'^(.+)\[\]$'); + for (String keyValuePair in body.split('&')) { if (keyValuePair.contains('=')) { List split = keyValuePair.split('='); String key = Uri.decodeQueryComponent(split[0]); String value = Uri.decodeQueryComponent(split[1]); - num numValue = num.parse(value, (_) => double.NAN); - if (!numValue.isNaN) - map[key] = numValue; - else if (value.startsWith('[') && value.endsWith(']')) - map[key] = god.deserialize(value); - else if (value.startsWith('{') && value.endsWith('}')) - map[key] = god.deserialize(value); - else if (value.trim().toLowerCase() == 'null') - map[key] = null; - else map[key] = value; + + if (parseArray.hasMatch(key)) { + Match queryMatch = parseArray.firstMatch(key); + key = queryMatch.group(1); + if (!(map[key] is List)) { + map[key] = []; + } + + map[key].add(getValue(value)); + } else if(key.contains('.')) { + // i.e. map.foo.bar => [map, foo, bar] + List keys = key.split('.'); + + Map targetMap = map[keys[0]] ?? {}; + map[keys[0]] = targetMap; + for (int i = 1; i < keys.length; i++) { + if (i < keys.length - 1) { + targetMap[keys[i]] = targetMap[keys[i]] ?? {}; + targetMap = targetMap[keys[i]]; + } else { + targetMap[keys[i]] = getValue(value); + } + } + } + else map[key] = getValue(value); } else map[Uri.decodeQueryComponent(keyValuePair)] = true; } +} + +getValue(String value) { + num numValue = num.parse(value, (_) => double.NAN); + if (!numValue.isNaN) + return numValue; + else if (value.startsWith('[') && value.endsWith(']')) + return JSON.decode(value); + else if (value.startsWith('{') && value.endsWith('}')) + return JSON.decode(value); + else if (value.trim().toLowerCase() == 'null') + return null; + else return value; } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 1bdc9254..75074e53 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,9 +1,8 @@ name: body_parser author: Tobe O -version: 1.0.0-dev +version: 1.0.0-beta description: Parse request bodies and query strings in Dart. -dependencies: - json_god: any dev_dependencies: http: any + json_god: any test: any \ No newline at end of file diff --git a/test/all_tests.dart b/test/all_tests.dart index e56d95f2..770b2101 100644 --- a/test/all_tests.dart +++ b/test/all_tests.dart @@ -42,15 +42,17 @@ main() { }); test('GET Complex', () async { - var postData = 'hello=world&nums[]=1&nums[]=2.0&nums[]=${3 - + var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 - 1}&map.foo.bar=baz'; + print('Body: $postData'); var response = await client.get('$url/?$postData'); - var body = god.deserialize(response.body)['body']; - expect(body['hello'], equals('world')); - expect(body['nums'][2], equals(2)); - expect(body['map'] is Map, equals(true)); - expect(body['map']['foo'], equals({'bar': 'baz'})); - }, skip: 'Array support via query string is pending.'); + print('Response: ${response.body}'); + var query = god.deserialize(response.body)['query']; + expect(query['hello'], equals('world')); + expect(query['nums'][2], equals(2)); + expect(query['map'] is Map, equals(true)); + expect(query['map']['foo'], equals({'bar': 'baz'})); + }); }); group('urlencoded', () { @@ -66,7 +68,7 @@ main() { }); test('Post Complex', () async { - var postData = 'hello=world&nums[]=1&nums[]=2.0&nums[]=${3 - + var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 - 1}&map.foo.bar=baz'; var response = await client.post(url, headers: headers, body: postData); var body = god.deserialize(response.body)['body']; @@ -74,7 +76,7 @@ main() { expect(body['nums'][2], equals(2)); expect(body['map'] is Map, equals(true)); expect(body['map']['foo'], equals({'bar': 'baz'})); - }, skip: 'Array support via urlencoded is pending.'); + }); }); group('JSON', () {