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
|
||||
.packages
|
||||
.project
|
||||
.pub/
|
||||
build/
|
||||
**/packages/
|
||||
packages
|
||||
.packages
|
||||
|
||||
# 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)
|
||||
# Or the files created by dart2js.
|
||||
*.dart.js
|
||||
*.part.js
|
||||
*.js_
|
||||
*.js.deps
|
||||
*.js.map
|
||||
*.info.json
|
||||
|
||||
# Directory created by dartdoc
|
||||
doc/api/
|
||||
|
||||
# Don't commit pubspec lock file
|
||||
# (Library packages only! Remove pattern if developing an application package)
|
||||
# Include when developing application packages.
|
||||
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