mirror of
https://github.com/dart-lang/sdk
synced 2024-09-22 22:33:55 +00:00
Move MimeMultipartTransformer and HttpBodyHandler to mime and http_server packages.
BUG= R=whesse@google.com Review URL: https://codereview.chromium.org//18438005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@24991 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
88d1ae1957
commit
40c7d89d66
|
@ -6,9 +6,14 @@ library http_server;
|
|||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:json' as JSON;
|
||||
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
part 'src/http_body.dart';
|
||||
part 'src/http_body_impl.dart';
|
||||
part 'src/http_multipart_form_data.dart';
|
||||
part 'src/http_multipart_form_data_impl.dart';
|
||||
part 'src/virtual_directory.dart';
|
||||
part 'src/virtual_host.dart';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of dart.io;
|
||||
part of http_server;
|
||||
|
||||
|
||||
/**
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of dart.io;
|
||||
part of http_server;
|
||||
|
||||
class _HttpBodyHandlerTransformer
|
||||
extends StreamEventTransformer<HttpRequest, HttpRequestBody> {
|
||||
|
@ -150,6 +150,24 @@ class _HttpBodyHandler {
|
|||
|
||||
return asBinary();
|
||||
}
|
||||
|
||||
// Utility function to synchronously decode a list of bytes.
|
||||
static String _decodeString(List<int> bytes,
|
||||
[Encoding encoding = Encoding.UTF_8]) {
|
||||
if (bytes.length == 0) return "";
|
||||
var string;
|
||||
var error;
|
||||
var controller = new StreamController(sync: true);
|
||||
controller.stream
|
||||
.transform(new StringDecoder(encoding))
|
||||
.listen((data) => string = data,
|
||||
onError: (e) => error = e);
|
||||
controller.add(bytes);
|
||||
controller.close();
|
||||
if (error != null) throw error;
|
||||
assert(string != null);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
class _HttpBodyFileUpload implements HttpBodyFileUpload {
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of dart.io;
|
||||
part of http_server;
|
||||
|
||||
|
||||
/**
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of dart.io;
|
||||
part of http_server;
|
||||
|
||||
|
||||
class _HttpMultipartFormData extends Stream implements HttpMultipartFormData {
|
||||
|
@ -136,4 +136,3 @@ class _HttpMultipartFormData extends Stream implements HttpMultipartFormData {
|
|||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
import 'dart:io';
|
||||
import 'dart:utf';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:http_server/http_server.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
void testHttpClientResponseBody() {
|
||||
void test(String mimeType,
|
||||
|
@ -30,20 +31,17 @@ void testHttpClientResponseBody() {
|
|||
.then((request) => request.close())
|
||||
.then(HttpBodyHandler.processResponse)
|
||||
.then((body) {
|
||||
if (shouldFail) Expect.fail("Error expected");
|
||||
Expect.equals(type, body.type);
|
||||
Expect.isNotNull(body.response);
|
||||
expect(shouldFail, isFalse);
|
||||
expect(body.type, equals(type));
|
||||
expect(body.response, isNotNull);
|
||||
switch (type) {
|
||||
case "text":
|
||||
Expect.equals(expectedBody, body.body);
|
||||
break;
|
||||
|
||||
case "json":
|
||||
Expect.mapEquals(expectedBody, body.body);
|
||||
expect(body.body, equals(expectedBody));
|
||||
break;
|
||||
|
||||
default:
|
||||
Expect.fail("bad body type");
|
||||
fail("bad body type");
|
||||
}
|
||||
}, onError: (error) {
|
||||
if (!shouldFail) throw error;
|
||||
|
@ -95,52 +93,49 @@ void testHttpServerRequestBody() {
|
|||
HttpServer.bind("127.0.0.1", 0).then((server) {
|
||||
server.transform(new HttpBodyHandler(defaultEncoding: defaultEncoding))
|
||||
.listen((body) {
|
||||
if (shouldFail) Expect.fail("Error expected");
|
||||
Expect.equals(type, body.type);
|
||||
expect(shouldFail, isFalse);
|
||||
expect(body.type, equals(type));
|
||||
switch (type) {
|
||||
case "text":
|
||||
Expect.equals(body.contentType.mimeType, "text/plain");
|
||||
Expect.equals(expectedBody, body.body);
|
||||
expect(body.contentType.mimeType, equals("text/plain"));
|
||||
expect(body.body, equals(expectedBody));
|
||||
break;
|
||||
|
||||
case "json":
|
||||
Expect.equals(body.contentType.mimeType, "application/json");
|
||||
Expect.mapEquals(expectedBody, body.body);
|
||||
expect(body.contentType.mimeType, equals("application/json"));
|
||||
expect(body.body, equals(expectedBody));
|
||||
break;
|
||||
|
||||
case "binary":
|
||||
Expect.equals(body.contentType, null);
|
||||
Expect.listEquals(expectedBody, body.body);
|
||||
expect(body.contentType, isNull);
|
||||
expect(body.body, equals(expectedBody));
|
||||
break;
|
||||
|
||||
case "form":
|
||||
var mimeType = body.contentType.mimeType;
|
||||
Expect.isTrue(
|
||||
mimeType == 'multipart/form-data' ||
|
||||
mimeType == 'application/x-www-form-urlencoded');
|
||||
Expect.setEquals(expectedBody.keys.toSet(),
|
||||
body.body.keys.toSet());
|
||||
expect(mimeType,
|
||||
anyOf(equals('multipart/form-data'),
|
||||
equals('application/x-www-form-urlencoded')));
|
||||
expect(body.body.keys.toSet(),
|
||||
equals(expectedBody.keys.toSet()));
|
||||
for (var key in expectedBody.keys) {
|
||||
if (body.body[key] is HttpBodyFileUpload) {
|
||||
Expect.equals(expectedBody[key]['contentType'],
|
||||
body.body[key].contentType.toString());
|
||||
Expect.equals(expectedBody[key]['filename'],
|
||||
body.body[key].filename);
|
||||
if (body.body[key].content is String) {
|
||||
Expect.equals(expectedBody[key]['content'],
|
||||
body.body[key].content);
|
||||
var found = body.body[key];
|
||||
var expected = expectedBody[key];
|
||||
if (found is HttpBodyFileUpload) {
|
||||
expect(found.contentType.toString(),
|
||||
equals(expected['contentType']));
|
||||
expect(found.filename,
|
||||
equals(expected['filename']));
|
||||
expect(found.content,
|
||||
equals(expected['content']));
|
||||
} else {
|
||||
Expect.listEquals(expectedBody[key]['content'],
|
||||
body.body[key].content);
|
||||
}
|
||||
} else {
|
||||
Expect.equals(expectedBody[key], body.body[key]);
|
||||
expect(found, equals(expected));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Expect.fail("bad body type");
|
||||
throw "bad body type";
|
||||
}
|
||||
body.response.close();
|
||||
}, onError: (error) {
|
||||
|
@ -159,7 +154,7 @@ void testHttpServerRequestBody() {
|
|||
})
|
||||
.then((response) {
|
||||
if (shouldFail) {
|
||||
Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
|
||||
expect(response.statusCode, equals(HttpStatus.BAD_REQUEST));
|
||||
}
|
||||
response.fold(null, (x, y) {});
|
||||
client.close();
|
|
@ -1,13 +1,10 @@
|
|||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// VMOptions=
|
||||
// VMOptions=--short_socket_read
|
||||
// VMOptions=--short_socket_write
|
||||
// VMOptions=--short_socket_read --short_socket_write
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "package:http_server/http_server.dart";
|
||||
import "package:mime/mime.dart";
|
||||
import "package:unittest/unittest.dart";
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
|
@ -76,7 +73,7 @@ void postDataTest(List<int> message,
|
|||
.fold([], (l, f) => l..add(f))
|
||||
.then(Future.wait)
|
||||
.then((fields) {
|
||||
Expect.listEquals(expectedFields, fields);
|
||||
expect(fields, equals(expectedFields));
|
||||
request.response.close().then((_) => server.close());
|
||||
});
|
||||
});
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
library mime;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
part 'src/mime_type.dart';
|
||||
part 'src/extension_map.dart';
|
||||
part 'src/magic_number.dart';
|
||||
part 'src/mime_multipart_transformer.dart';
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of dart.io;
|
||||
part of mime;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,21 @@ class _MimeMultipart extends MimeMultipart {
|
|||
}
|
||||
}
|
||||
|
||||
class _Const {
|
||||
// Bytes for '()<>@,;:\\"/[]?={} \t'.
|
||||
static const SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47,
|
||||
91, 93, 63, 61, 123, 125, 32, 9];
|
||||
}
|
||||
|
||||
class _CharCode {
|
||||
static const int HT = 9;
|
||||
static const int LF = 10;
|
||||
static const int CR = 13;
|
||||
static const int SP = 32;
|
||||
static const int DASH = 45;
|
||||
static const int COLON = 58;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser for MIME multipart types of data as described in RFC 2046
|
||||
* section 5.1.1. The data is transformed into [MimeMultipart] objects, each
|
||||
|
@ -398,7 +413,7 @@ class MimeMultipartTransformer
|
|||
}
|
||||
|
||||
|
||||
class MimeMultipartException implements IOException {
|
||||
class MimeMultipartException implements Exception {
|
||||
const MimeMultipartException([String this.message = ""]);
|
||||
String toString() => "MimeMultipartException: $message";
|
||||
final String message;
|
|
@ -2,10 +2,10 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "package:unittest/unittest.dart";
|
||||
import "package:mime/mime.dart";
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
void testParse(String message,
|
||||
|
@ -13,33 +13,32 @@ void testParse(String message,
|
|||
[List<Map> expectedHeaders,
|
||||
List expectedParts,
|
||||
bool expectError = false]) {
|
||||
void testWrite(List<int> data, [int chunkSize = -1]) {
|
||||
Future testWrite(List<int> data, [int chunkSize = -1]) {
|
||||
StreamController controller = new StreamController(sync: true);
|
||||
|
||||
var stream = controller.stream.transform(
|
||||
new MimeMultipartTransformer(boundary));
|
||||
int i = 0;
|
||||
var port = new ReceivePort();
|
||||
var completer = new Completer();
|
||||
var futures = [];
|
||||
stream.listen((multipart) {
|
||||
int part = i++;
|
||||
if (expectedHeaders != null) {
|
||||
Expect.mapEquals(expectedHeaders[part], multipart.headers);
|
||||
expect(multipart.headers, equals(expectedHeaders[part]));
|
||||
}
|
||||
var partPort = new ReceivePort();
|
||||
multipart.fold([], (buffer, data) => buffer..addAll(data))
|
||||
futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data))
|
||||
.then((data) {
|
||||
if (expectedParts[part] != null) {
|
||||
Expect.listEquals(expectedParts[part].codeUnits, data);
|
||||
expect(data, equals(expectedParts[part].codeUnits));
|
||||
}
|
||||
partPort.close();
|
||||
});
|
||||
}));
|
||||
}, onError: (error) {
|
||||
if (!expectError) throw error;
|
||||
}, onDone: () {
|
||||
if (expectedParts != null) {
|
||||
Expect.equals(expectedParts.length, i);
|
||||
expect(i, equals(expectedParts.length));
|
||||
}
|
||||
port.close();
|
||||
Future.wait(futures).then(completer.complete);
|
||||
});
|
||||
|
||||
if (chunkSize == -1) chunkSize = data.length;
|
||||
|
@ -52,15 +51,19 @@ void testParse(String message,
|
|||
written += writeLength;
|
||||
}
|
||||
controller.close();
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
// Test parsing the data three times delivering the data in
|
||||
// different chunks.
|
||||
List<int> data = message.codeUnits;
|
||||
testWrite(data);
|
||||
testWrite(data, 10);
|
||||
testWrite(data, 2);
|
||||
testWrite(data, 1);
|
||||
expect(Future.wait([
|
||||
testWrite(data),
|
||||
testWrite(data, 10),
|
||||
testWrite(data, 2),
|
||||
testWrite(data, 1)]),
|
||||
completes);
|
||||
}
|
||||
|
||||
void testParseValid() {
|
|
@ -35,14 +35,16 @@ _getHttpRequestResponseCode() => _httpRequestResponseCode;
|
|||
_getHttpRequestStatusString() => _httpRequestStatusString;
|
||||
_getHttpRequestResponse() => _httpRequestResponse;
|
||||
|
||||
void _requestCompleted(HttpClientResponseBody body) {
|
||||
_httpRequestResponseCode = body.statusCode;
|
||||
_httpRequestStatusString = '${body.statusCode} ${body.reasonPhrase}';
|
||||
void _requestCompleted(List<int> data, HttpClientResponse response) {
|
||||
_httpRequestResponseCode = response.statusCode;
|
||||
_httpRequestStatusString = '${response.statusCode} ${response.reasonPhrase}';
|
||||
_httpRequestResponse = null;
|
||||
if (body.statusCode != 200 || body.type == 'json') {
|
||||
if (response.statusCode != 200 ||
|
||||
(response.headers.contentType != null &&
|
||||
response.headers.contentType.mimeType == 'application/json')) {
|
||||
return;
|
||||
}
|
||||
_httpRequestResponse = body.body;
|
||||
_httpRequestResponse = data;
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,9 +63,12 @@ void _makeHttpRequest(String uri) {
|
|||
Uri requestUri = Uri.parse(uri);
|
||||
_client.getUrl(requestUri)
|
||||
.then((HttpClientRequest request) => request.close())
|
||||
.then(HttpBodyHandler.processResponse)
|
||||
.then((HttpClientResponseBody body) {
|
||||
_requestCompleted(body);
|
||||
.then((HttpClientResponse response) {
|
||||
return response
|
||||
.fold(new BytesBuilder(), (b, d) => b..add(d))
|
||||
.then((builder) {
|
||||
_requestCompleted(builder.takeBytes(), response);
|
||||
});
|
||||
}).catchError((error) {
|
||||
_requestFailed(error);
|
||||
});
|
||||
|
|
|
@ -503,7 +503,6 @@ bool isUserFacingException(error) {
|
|||
error is HttpException ||
|
||||
error is HttpException ||
|
||||
error is LinkException ||
|
||||
error is MimeMultipartException ||
|
||||
error is OSError ||
|
||||
error is ProcessException ||
|
||||
error is SocketException ||
|
||||
|
|
|
@ -34,18 +34,13 @@ part 'file.dart';
|
|||
part 'file_impl.dart';
|
||||
part 'file_system_entity.dart';
|
||||
part 'http.dart';
|
||||
part 'http_body.dart';
|
||||
part 'http_body_impl.dart';
|
||||
part 'http_date.dart';
|
||||
part 'http_headers.dart';
|
||||
part 'http_impl.dart';
|
||||
part 'http_multipart_form_data.dart';
|
||||
part 'http_multipart_form_data_impl.dart';
|
||||
part 'http_parser.dart';
|
||||
part 'http_session.dart';
|
||||
part 'io_sink.dart';
|
||||
part 'link.dart';
|
||||
part 'mime_multipart_parser.dart';
|
||||
part 'options.dart';
|
||||
part 'path.dart';
|
||||
part 'path_impl.dart';
|
||||
|
|
|
@ -15,18 +15,13 @@
|
|||
'file_impl.dart',
|
||||
'file_system_entity.dart',
|
||||
'http.dart',
|
||||
'http_body.dart',
|
||||
'http_body_impl.dart',
|
||||
'http_date.dart',
|
||||
'http_headers.dart',
|
||||
'http_impl.dart',
|
||||
'http_multipart_form_data.dart',
|
||||
'http_multipart_form_data_impl.dart',
|
||||
'http_parser.dart',
|
||||
'http_session.dart',
|
||||
'io_sink.dart',
|
||||
'link.dart',
|
||||
'mime_multipart_parser.dart',
|
||||
'options.dart',
|
||||
'path.dart',
|
||||
'path_impl.dart',
|
||||
|
|
Loading…
Reference in a new issue