+5
This commit is contained in:
parent
331e7aa14c
commit
1acfeeee24
6 changed files with 77 additions and 24 deletions
|
@ -1,5 +1,5 @@
|
|||
# Body Parser
|
||||
![version 1.0.0-dev+3](https://img.shields.io/badge/version-1.0.0--dev+3-red.svg)
|
||||
![version 1.0.0-dev+5](https://img.shields.io/badge/version-1.0.0--dev+5-red.svg)
|
||||
![build status](https://travis-ci.org/thosakwe/body_parser.svg)
|
||||
|
||||
**NOT YET PRODUCTION READY**
|
||||
|
@ -68,4 +68,4 @@ Thank you for using this library. I hope you like it.
|
|||
|
||||
Feel free to follow me on Twitter:
|
||||
|
||||
[@_wapaa_](http://twitter.com/_wapaa_)
|
||||
[@thosakwe](http://twitter.com/thosakwe)
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/// A library for parsing HTTP request bodies and queries.
|
||||
library body_parser;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
export 'src/body_parser.dart';
|
||||
export 'src/body_parse_result.dart';
|
||||
export 'src/file_upload_info.dart';
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import 'file_upload_info.dart';
|
||||
|
||||
/// A representation of data from an incoming request.
|
||||
class BodyParseResult {
|
||||
abstract class BodyParseResult {
|
||||
/// The parsed body.
|
||||
Map body = {};
|
||||
Map<String, dynamic> get body;
|
||||
|
||||
/// The parsed query string.
|
||||
Map query = {};
|
||||
Map<String, dynamic> get query;
|
||||
|
||||
/// All files uploaded within this request.
|
||||
List<FileUploadInfo> files = [];
|
||||
List<FileUploadInfo> get files;
|
||||
|
||||
/// The original body bytes sent with this request.
|
||||
///
|
||||
/// You must set [storeOriginalBuffer] to `true` to see this.
|
||||
List<int> get originalBuffer;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:io';
|
|||
import 'package:http_server/http_server.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'body_parse_result.dart';
|
||||
import 'chunk.dart';
|
||||
import 'file_upload_info.dart';
|
||||
import 'map_from_uri.dart';
|
||||
|
||||
|
@ -14,14 +13,41 @@ import 'map_from_uri.dart';
|
|||
/// On a file upload request, only fields with the name **'file'** are processed
|
||||
/// as files. Anything else is put in the body. You can change the upload file name
|
||||
/// via the *fileUploadName* parameter. :)
|
||||
Future<BodyParseResult> parseBody(HttpRequest request) async {
|
||||
var result = new BodyParseResult();
|
||||
///
|
||||
/// Use [storeOriginalBuffer] to add the original request bytes to the result.
|
||||
Future<BodyParseResult> parseBody(HttpRequest request,
|
||||
{bool storeOriginalBuffer: false}) async {
|
||||
var result = new _BodyParseResultImpl();
|
||||
|
||||
Future<List<int>> getBytes() async {
|
||||
return await request.fold(<int>[], (a, b) => a..addAll(b));
|
||||
}
|
||||
|
||||
Future<String> getBody() async {
|
||||
if (storeOriginalBuffer) {
|
||||
List<int> bytes = await getBytes();
|
||||
return UTF8.decode(result.originalBuffer = bytes);
|
||||
} else
|
||||
return await request.transform(UTF8.decoder).join();
|
||||
}
|
||||
|
||||
try {
|
||||
if (request.headers.contentType != null) {
|
||||
if (request.headers.contentType.primaryType == 'multipart' &&
|
||||
request.headers.contentType.parameters.containsKey('boundary')) {
|
||||
var parts = request
|
||||
Stream<List<int>> stream;
|
||||
|
||||
if (storeOriginalBuffer) {
|
||||
var bytes = result.originalBuffer = await getBytes();
|
||||
var ctrl = new StreamController<List<int>>()
|
||||
..add(bytes)
|
||||
..close();
|
||||
stream = ctrl.stream;
|
||||
} else {
|
||||
stream = request;
|
||||
}
|
||||
|
||||
var parts = stream
|
||||
.transform(new MimeMultipartTransformer(
|
||||
request.headers.contentType.parameters['boundary']))
|
||||
.map((part) =>
|
||||
|
@ -47,11 +73,10 @@ Future<BodyParseResult> parseBody(HttpRequest request) async {
|
|||
}
|
||||
} else if (request.headers.contentType.mimeType ==
|
||||
ContentType.JSON.mimeType) {
|
||||
result.body
|
||||
.addAll(JSON.decode(await request.transform(UTF8.decoder).join()));
|
||||
result.body.addAll(JSON.decode(await getBody()));
|
||||
} else if (request.headers.contentType.mimeType ==
|
||||
'application/x-www-form-urlencoded') {
|
||||
String body = await request.transform(UTF8.decoder).join();
|
||||
String body = await getBody();
|
||||
buildMapFromUri(result.body, body);
|
||||
}
|
||||
} else if (request.uri.hasQuery) {
|
||||
|
@ -63,3 +88,17 @@ Future<BodyParseResult> parseBody(HttpRequest request) async {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
class _BodyParseResultImpl implements BodyParseResult {
|
||||
@override
|
||||
Map<String, dynamic> body = {};
|
||||
|
||||
@override
|
||||
List<FileUploadInfo> files = [];
|
||||
|
||||
@override
|
||||
List<int> originalBuffer;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> query = {};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: body_parser
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
version: 1.0.0-dev+4
|
||||
version: 1.0.0-dev+5
|
||||
description: Parse request bodies and query strings in Dart.
|
||||
homepage: https://github.com/thosakwe/body_parser
|
||||
dependencies:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:body_parser/body_parser.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
@ -16,7 +17,8 @@ main() {
|
|||
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)));
|
||||
request.response.write(
|
||||
god.serialize(await parseBody(request, storeOriginalBuffer: true)));
|
||||
await request.response.close();
|
||||
});
|
||||
url = 'http://localhost:${server.port}';
|
||||
|
@ -36,8 +38,11 @@ main() {
|
|||
print('GET $url/?hello=world');
|
||||
var response = await client.get('$url/?hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{},"query":{"hello":"world"},"files":[]}'));
|
||||
var result = JSON.decode(response.body);
|
||||
expect(result['body'], equals({}));
|
||||
expect(result['query'], equals({'hello': 'world'}));
|
||||
expect(result['files'], equals([]));
|
||||
expect(result['originalBuffer'], isNull);
|
||||
});
|
||||
|
||||
test('GET Complex', () async {
|
||||
|
@ -72,8 +77,12 @@ main() {
|
|||
var response =
|
||||
await client.post(url, headers: headers, body: 'hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{"hello":"world"},"query":{},"files":[]}'));
|
||||
var result = JSON.decode(response.body);
|
||||
expect(result['query'], equals({}));
|
||||
expect(result['body'], equals({'hello': 'world'}));
|
||||
expect(result['files'], equals([]));
|
||||
expect(result['originalBuffer'], isList);
|
||||
expect(result['originalBuffer'], isNotEmpty);
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
|
@ -104,8 +113,11 @@ main() {
|
|||
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":{},"files":[]}'));
|
||||
var result = JSON.decode(response.body);
|
||||
expect(result['body'], equals({'hello': 'world'}));
|
||||
expect(result['query'], equals({}));
|
||||
expect(result['files'], equals([]));
|
||||
expect(result['originalBuffer'], allOf(isList, isNotEmpty));
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
|
|
Loading…
Reference in a new issue