Next comes array support.

This commit is contained in:
regiostech 2016-03-03 23:30:13 -05:00
parent f41f367808
commit c63ee84acb
4 changed files with 188 additions and 26 deletions

View file

@ -1,2 +1,72 @@
# body_parser # Body Parser
![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev-red.svg)
**NOT YET PRODUCTION READY**
Parse request bodies and query strings in Dart. Parse request bodies and query strings in Dart.
### Contents
* [Body Parser](#body-parser)
* [About](#about)
* [Installation](#installation)
* [Usage](#usage)
* [Thanks](#thank-you-for-using-body_parser)
# About
I needed something like Express.js's `body-parser` module, so I made it here. It fully supports JSON requests.
x-www-form-urlencoded is partially supported, as well as query strings. By the next update, they will be fully supported.
The only missing link in the implementation is that I have not yet provided support for arrays in the query. File upload support
will also be present by the production 1.0.0 release.
A benefit of this is that primitive types are automatically deserialized correctly. As in, if you have a `hello=1.5` request, then
`body['hello']` will equal `1.5` and not `'1.5'`. A very semantic difference, yes, but it relieves stress in my head.
# Installation
To install Body Parser for your Dart project, simply add body_parser to your
pub dependencies.
dependencies:
body_parser: any
# Usage
Body Parser exposes a simple class called [BodyParseResult].
You can easily parse the query string and request body for a request by calling `Future<BodyParseResult> parseBody`.
```dart
import 'dart:convert';
import 'package:body_parser/body_parser.dart';
main() async {
// ...
await for (HttpRequest request in server) {
request.response.write(JSON.encode(await parseBody(request).body));
await request.response.close();
}
}
```
This can easily be used with a library like [JSON God](https://github.com/thosakwe/json_god)
to build structured JSON/REST APIs. Add validation and you've got an instant backend.
```dart
MyClass create(HttpRequest request) async {
God god = new God();
return god.deserialize(await parseBody(request).body, MyClass);
}
```
# Thank you for using Body Parser
Thank you for using this library. I hope you like it.
Feel free to follow me on Twitter:
[@thosakwe](http://twitter.com/thosakwe)
or
[@regios_tech](http://twitter.com/regios_tech)

View file

@ -572,8 +572,8 @@ jQuery.cookie = function(name, value, options) {
<body> <body>
<div id="container"> <div id="container">
<div id="header"> <div id="header">
<div class="time">922 ms</div> <div class="time">656 ms</div>
<h1>Run All Tests: <strong><span class="total">2 total, </span><span class="failed">1 failed, </span><span class="passed">1 passed</span></strong> <h1>Run All Tests: <strong><span class="total">6 total, </span><span class="ignored">2 ignored, </span><span class="passed">4 passed</span></strong>
</h1> </h1>
<div id="treecontrol"> <div id="treecontrol">
<ul> <ul>
@ -591,34 +591,71 @@ jQuery.cookie = function(name, value, options) {
<ul id="tree"> <ul id="tree">
<li xmlns="" class="level top ignored open"> <li xmlns="" class="level top ignored open">
<span><em class="time"> <span><em class="time">
<div class="time">922 ms</div> <div class="time">656 ms</div>
</em>Test server support</span> </em>Test server support</span>
<ul> <ul>
<li class="level suite failed open"> <li class="level suite ignored open">
<span><em class="time"> <span><em class="time">
<div class="time">922 ms</div> <div class="time">477 ms</div>
</em>query string</span>
<ul>
<li class="level test">
<span><em class="time">
<div class="time">477 ms</div>
</em><em class="status">passed</em>GET Simple</span>
<ul>
<li class="text">
<span class="stdout">Test server listening on http://localhost:62263<br/>GET http://localhost:62263/?hello=world<br/>Response: {&quot;body&quot;:{},&quot;query&quot;:{&quot;hello&quot;:&quot;world&quot;}}<br/></span>
</li>
</ul>
</li>
<li class="level test ignored open">
<span><em class="time"></em><em class="status">ignored</em>GET Complex</span>
</li>
</ul>
</li>
<li class="level suite ignored open">
<span><em class="time">
<div class="time">53 ms</div>
</em>urlencoded</span>
<ul>
<li class="level test">
<span><em class="time">
<div class="time">53 ms</div>
</em><em class="status">passed</em>POST Simple</span>
<ul>
<li class="text">
<span class="stdout">Test server listening on http://localhost:62265<br/>Body: hello=world<br/>Response: {&quot;body&quot;:{&quot;hello&quot;:&quot;world&quot;},&quot;query&quot;:{}}<br/></span>
</li>
</ul>
</li>
<li class="level test ignored open">
<span><em class="time"></em><em class="status">ignored</em>Post Complex</span>
</li>
</ul>
</li>
<li class="level suite open">
<span><em class="time">
<div class="time">126 ms</div>
</em>JSON</span> </em>JSON</span>
<ul> <ul>
<li class="level test"> <li class="level test">
<span><em class="time"> <span><em class="time">
<div class="time">528 ms</div> <div class="time">85 ms</div>
</em><em class="status">passed</em>Post Simple JSON</span> </em><em class="status">passed</em>Post Simple</span>
<ul> <ul>
<li class="text"> <li class="text">
<span class="stdout">Test server listening on http://localhost:60667<br/></span> <span class="stdout">Test server listening on http://localhost:62267<br/>Body: {&quot;hello&quot;:&quot;world&quot;}<br/>Response: {&quot;body&quot;:{&quot;hello&quot;:&quot;world&quot;},&quot;query&quot;:{}}<br/></span>
</li> </li>
</ul> </ul>
</li> </li>
<li class="level test failed open"> <li class="level test">
<span><em class="time"> <span><em class="time">
<div class="time">394 ms</div> <div class="time">41 ms</div>
</em><em class="status">failed</em>Post Complex JSON</span> </em><em class="status">passed</em>Post Complex</span>
<ul> <ul>
<li class="text"> <li class="text">
<span class="stdout">Test server listening on http://localhost:60669<br/></span> <span class="stdout">Test server listening on http://localhost:62269<br/>Body: {&quot;hello&quot;:&quot;world&quot;,&quot;nums&quot;:[1,2.0,2],&quot;map&quot;:{&quot;foo&quot;:{&quot;bar&quot;:&quot;baz&quot;}}}<br/>Response: {&quot;body&quot;:{&quot;hello&quot;:&quot;world&quot;,&quot;nums&quot;:[1,2.0,2],&quot;map&quot;:{&quot;foo&quot;:{&quot;bar&quot;:&quot;baz&quot;}}},&quot;query&quot;:{}}<br/></span>
</li>
<li class="text">
<span class="stderr">package:test expect<br/>test\all_tests.dart 56:9 main.&lt;fn&gt;.&lt;fn&gt;.&lt;fn&gt;.&lt;async&gt;<br/>===== asynchronous gap ===========================<br/>dart:async _Completer.completeError<br/>test\all_tests.dart 57:8 main.&lt;fn&gt;.&lt;fn&gt;.&lt;fn&gt;.&lt;async&gt;<br/>===== asynchronous gap ===========================<br/>dart:async _asyncThenWrapperHelper<br/>test\all_tests.dart main.&lt;fn&gt;.&lt;fn&gt;.&lt;fn&gt;<br/></span>
</li> </li>
</ul> </ul>
</li> </li>
@ -630,7 +667,7 @@ jQuery.cookie = function(name, value, options) {
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
<p>Generated by WebStorm on 3/3/16 10:43 PM</p> <p>Generated by WebStorm on 3/3/16 11:11 PM</p>
</div> </div>
</body> </body>
</html> </html>

View file

@ -1,5 +1,4 @@
// A library for parsing HTTP request bodies and queries. /// A library for parsing HTTP request bodies and queries.
library body_parser; library body_parser;
import 'dart:async'; import 'dart:async';

View file

@ -33,15 +33,66 @@ main() {
god = null; god = null;
}); });
group('JSON', () { group('query string', () {
test('Post Simple JSON', () async { test('GET Simple', () async {
var response = await client.post(url, body: { print('GET $url/?hello=world');
'hello': 'world' var response = await client.get('$url/?hello=world');
print('Response: ${response.body}');
expect(response.body, equals('{"body":{},"query":{"hello":"world"}}'));
}); });
test('GET Complex', () async {
var postData = 'hello=world&nums[]=1&nums[]=2.0&nums[]=${3 -
1}&map.foo.bar=baz';
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.');
});
group('urlencoded', () {
Map<String, String> headers = {
HttpHeaders.CONTENT_TYPE: 'application/x-www-form-urlencoded'
};
test('POST Simple', () async {
print('Body: hello=world');
var response = await client.post(
url, headers: headers, body: 'hello=world');
print('Response: ${response.body}');
expect(response.body, equals('{"body":{"hello":"world"},"query":{}}')); expect(response.body, equals('{"body":{"hello":"world"},"query":{}}'));
}); });
test('Post Complex JSON', () async { test('Post Complex', () async {
var postData = 'hello=world&nums[]=1&nums[]=2.0&nums[]=${3 -
1}&map.foo.bar=baz';
var response = await client.post(url, headers: headers, body: 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 urlencoded is pending.');
});
group('JSON', () {
Map<String, String> headers = {
HttpHeaders.CONTENT_TYPE: ContentType.JSON.toString()
};
test('Post Simple', () async {
var postData = god.serialize({
'hello': 'world'
});
print('Body: $postData');
var response = await client.post(
url, headers: headers, body: postData);
print('Response: ${response.body}');
expect(response.body, equals('{"body":{"hello":"world"},"query":{}}'));
});
test('Post Complex', () async {
var postData = god.serialize({ var postData = god.serialize({
'hello': 'world', 'hello': 'world',
'nums': [1, 2.0, 3 - 1], 'nums': [1, 2.0, 3 - 1],
@ -51,9 +102,14 @@ main() {
} }
} }
}); });
var response = await client.post(url, body: postData); print('Body: $postData');
var response = await client.post(url, headers: headers, body: postData);
print('Response: ${response.body}');
var body = god.deserialize(response.body)['body']; var body = god.deserialize(response.body)['body'];
expect(body['hello'], equals('world')); 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'}));
}); });
}); });
}); });