Next comes array support.
This commit is contained in:
parent
f41f367808
commit
c63ee84acb
4 changed files with 188 additions and 26 deletions
72
README.md
72
README.md
|
@ -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)
|
|
@ -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: {"body":{},"query":{"hello":"world"}}<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: {"body":{"hello":"world"},"query":{}}<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: {"hello":"world"}<br/>Response: {"body":{"hello":"world"},"query":{}}<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: {"hello":"world","nums":[1,2.0,2],"map":{"foo":{"bar":"baz"}}}<br/>Response: {"body":{"hello":"world","nums":[1,2.0,2],"map":{"foo":{"bar":"baz"}}},"query":{}}<br/></span>
|
||||||
</li>
|
|
||||||
<li class="text">
|
|
||||||
<span class="stderr">package:test expect<br/>test\all_tests.dart 56:9 main.<fn>.<fn>.<fn>.<async><br/>===== asynchronous gap ===========================<br/>dart:async _Completer.completeError<br/>test\all_tests.dart 57:8 main.<fn>.<fn>.<fn>.<async><br/>===== asynchronous gap ===========================<br/>dart:async _asyncThenWrapperHelper<br/>test\all_tests.dart main.<fn>.<fn>.<fn><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>
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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'}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue