Tests failing + incomplete
This commit is contained in:
parent
76af2710af
commit
f41f367808
5 changed files with 830 additions and 17 deletions
75
.gitignore
vendored
75
.gitignore
vendored
|
@ -1,27 +1,68 @@
|
||||||
# See https://www.dartlang.org/tools/private-files.html
|
### VisualStudioCode template
|
||||||
|
.settings
|
||||||
|
|
||||||
# Files and directories created by pub
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
## Directory-based project format:
|
||||||
|
.idea/
|
||||||
|
/Test Results - Run_All_Tests.html
|
||||||
|
# if you remove the above rule, at least ignore the following:
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
# .idea/workspace.xml
|
||||||
|
# .idea/tasks.xml
|
||||||
|
# .idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
# .idea/dataSources.ids
|
||||||
|
# .idea/dataSources.xml
|
||||||
|
# .idea/sqlDataSources.xml
|
||||||
|
# .idea/dynamic.xml
|
||||||
|
# .idea/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
# .idea/gradle.xml
|
||||||
|
# .idea/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
# .idea/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
### Dart template
|
||||||
|
# Don’t commit the following directories created by pub.
|
||||||
.buildlog
|
.buildlog
|
||||||
.packages
|
|
||||||
.project
|
|
||||||
.pub/
|
.pub/
|
||||||
build/
|
build/
|
||||||
**/packages/
|
packages
|
||||||
|
.packages
|
||||||
|
|
||||||
# Files created by dart2js
|
# Or the files created by dart2js.
|
||||||
# (Most Dart developers will use pub build to compile Dart, use/modify these
|
|
||||||
# rules if you intend to use dart2js directly
|
|
||||||
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
|
|
||||||
# differentiate from explicit Javascript files)
|
|
||||||
*.dart.js
|
*.dart.js
|
||||||
*.part.js
|
*.js_
|
||||||
*.js.deps
|
*.js.deps
|
||||||
*.js.map
|
*.js.map
|
||||||
*.info.json
|
|
||||||
|
|
||||||
# Directory created by dartdoc
|
# Include when developing application packages.
|
||||||
doc/api/
|
|
||||||
|
|
||||||
# Don't commit pubspec lock file
|
|
||||||
# (Library packages only! Remove pattern if developing an application package)
|
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
|
|
||||||
|
|
636
Test Results - Run_All_Tests.html
Normal file
636
Test Results - Run_All_Tests.html
Normal file
File diff suppressed because one or more lines are too long
67
lib/body_parser.dart
Normal file
67
lib/body_parser.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
// A library for parsing HTTP request bodies and queries.
|
||||||
|
|
||||||
|
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 {
|
||||||
|
/// The parsed body.
|
||||||
|
Map body = {};
|
||||||
|
|
||||||
|
/// The parsed query string.
|
||||||
|
Map query = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grabs data from an incoming request.
|
||||||
|
///
|
||||||
|
/// Supports urlencoded and JSON.
|
||||||
|
Future<BodyParseResult> parseBody(HttpRequest request) async {
|
||||||
|
BodyParseResult result = new BodyParseResult();
|
||||||
|
ContentType contentType = request.headers.contentType;
|
||||||
|
|
||||||
|
// Parse body
|
||||||
|
if (contentType != null) {
|
||||||
|
if (contentType.mimeType == 'application/json')
|
||||||
|
result.body = JSON.decode(await request.transform(UTF8.decoder).join());
|
||||||
|
else if (contentType.mimeType == 'application/x-www-form-urlencoded') {
|
||||||
|
String body = await request.transform(UTF8.decoder).join();
|
||||||
|
buildMapFromUri(result.body, body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse query
|
||||||
|
RegExp queryRgx = new RegExp(r'\?(.+)$');
|
||||||
|
String uriString = request.requestedUri.toString();
|
||||||
|
if (queryRgx.hasMatch(uriString)) {
|
||||||
|
Match queryMatch = queryRgx.firstMatch(uriString);
|
||||||
|
buildMapFromUri(result.query, queryMatch.group(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses a URI-encoded string into real data! **Wow!**
|
||||||
|
buildMapFromUri(Map map, String body) {
|
||||||
|
God god = new God();
|
||||||
|
for (String keyValuePair in body.split('&')) {
|
||||||
|
if (keyValuePair.contains('=')) {
|
||||||
|
List<String> 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;
|
||||||
|
} else map[Uri.decodeQueryComponent(keyValuePair)] = true;
|
||||||
|
}
|
||||||
|
}
|
9
pubspec.yaml
Normal file
9
pubspec.yaml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
name: body_parser
|
||||||
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
|
version: 1.0.0-dev
|
||||||
|
description: Parse request bodies and query strings in Dart.
|
||||||
|
dependencies:
|
||||||
|
json_god: any
|
||||||
|
dev_dependencies:
|
||||||
|
http: any
|
||||||
|
test: any
|
60
test/all_tests.dart
Normal file
60
test/all_tests.dart
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:body_parser/body_parser.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:json_god/json_god.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('Test server support', () {
|
||||||
|
HttpServer server;
|
||||||
|
String url;
|
||||||
|
http.Client client;
|
||||||
|
God god;
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||||
|
server.listen((HttpRequest request) async {
|
||||||
|
//Server will simply return a JSON representation of the parsed body
|
||||||
|
request.response.write(god.serialize(await parseBody(request)));
|
||||||
|
await request.response.close();
|
||||||
|
});
|
||||||
|
url = 'http://localhost:${server.port}';
|
||||||
|
print('Test server listening on $url');
|
||||||
|
client = new http.Client();
|
||||||
|
god = new God();
|
||||||
|
});
|
||||||
|
tearDown(() async {
|
||||||
|
await server.close(force: true);
|
||||||
|
client.close();
|
||||||
|
server = null;
|
||||||
|
url = null;
|
||||||
|
client = null;
|
||||||
|
god = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
group('JSON', () {
|
||||||
|
test('Post Simple JSON', () async {
|
||||||
|
var response = await client.post(url, body: {
|
||||||
|
'hello': 'world'
|
||||||
|
});
|
||||||
|
expect(response.body, equals('{"body":{"hello":"world"},"query":{}}'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Post Complex JSON', () async {
|
||||||
|
var postData = god.serialize({
|
||||||
|
'hello': 'world',
|
||||||
|
'nums': [1, 2.0, 3 - 1],
|
||||||
|
'map': {
|
||||||
|
'foo': {
|
||||||
|
'bar': 'baz'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var response = await client.post(url, body: postData);
|
||||||
|
var body = god.deserialize(response.body)['body'];
|
||||||
|
expect(body['hello'], equals('world'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue