diff --git a/.analysis-options b/.analysis-options
new file mode 100644
index 00000000..518eb901
--- /dev/null
+++ b/.analysis-options
@@ -0,0 +1,2 @@
+analyzer:
+ strong-mode: true
\ No newline at end of file
diff --git a/.idea/angel_proxy.iml b/.idea/angel_proxy.iml
index a928d34a..3889dae0 100644
--- a/.idea/angel_proxy.iml
+++ b/.idea/angel_proxy.iml
@@ -12,7 +12,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests.xml
new file mode 100644
index 00000000..107ff326
--- /dev/null
+++ b/.idea/runConfigurations/All_Tests.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Pub_Serve_Tests.xml b/.idea/runConfigurations/Pub_Serve_Tests.xml
new file mode 100644
index 00000000..74e5219a
--- /dev/null
+++ b/.idea/runConfigurations/Pub_Serve_Tests.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 7b720dc0..672b0f5c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# angel_proxy
-[![version 1.0.2](https://img.shields.io/badge/version-1.0.2-brightgreen.svg)](https://pub.dartlang.org/packages/angel_proxy)
+[![version 1.0.3](https://img.shields.io/badge/version-1.0.3-brightgreen.svg)](https://pub.dartlang.org/packages/angel_proxy)
[![build status](https://travis-ci.org/angel-dart/proxy.svg)](https://travis-ci.org/angel-dart/proxy)
Angel middleware to forward requests to another server (i.e. pub serve).
diff --git a/lib/src/proxy_layer.dart b/lib/src/proxy_layer.dart
index 49b1f474..1fbf1d7a 100644
--- a/lib/src/proxy_layer.dart
+++ b/lib/src/proxy_layer.dart
@@ -1,4 +1,3 @@
-import 'dart:convert';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
@@ -43,7 +42,7 @@ class ProxyLayer {
Angel app;
HttpClient _client;
String _prefix;
- final bool debug;
+ final bool debug, streamToIO;
final String host, mapTo, publicPath;
final int port;
final String protocol;
@@ -53,6 +52,7 @@ class ProxyLayer {
this.mapTo: '/',
this.publicPath: '/',
this.protocol: 'http',
+ this.streamToIO: false,
SecurityContext securityContext}) {
_client = new HttpClient(context: securityContext);
_prefix = publicPath.replaceAll(_straySlashes, '');
@@ -118,11 +118,29 @@ class ProxyLayer {
..statusCode = rs.statusCode
..contentType = rs.headers.contentType;
- rs.headers.forEach((k, v) {
- res.headers[k] = v.join(',');
- });
+ _printDebug('Proxy response headers:\n${rs.headers}');
- await rs.forEach(res.buffer.add);
- return false;
+ if (streamToIO == true) {
+ res
+ ..willCloseItself = true
+ ..end();
+
+ copyHeaders(rs.headers, res.io.headers);
+
+ if (rs.headers[HttpHeaders.CONTENT_ENCODING] != null)
+ res.io.headers.set(HttpHeaders.CONTENT_ENCODING,
+ rs.headers[HttpHeaders.CONTENT_ENCODING]);
+
+ await rs.pipe(res.io);
+ } else {
+ rs.headers.forEach((k, v) {
+ if (k != HttpHeaders.CONTENT_ENCODING || !v.contains('gzip'))
+ res.headers[k] = v.join(',');
+ });
+
+ await rs.forEach(res.buffer.add);
+ }
+
+ return res.buffer.isEmpty;
}
}
diff --git a/lib/src/pub_serve_layer.dart b/lib/src/pub_serve_layer.dart
index c963d7ac..bb36f850 100644
--- a/lib/src/pub_serve_layer.dart
+++ b/lib/src/pub_serve_layer.dart
@@ -4,6 +4,7 @@ import 'proxy_layer.dart';
class PubServeLayer extends ProxyLayer {
PubServeLayer(
{bool debug: false,
+ bool streamToIO: true,
String host: 'localhost',
String mapTo: '/',
int port: 8080,
@@ -13,7 +14,8 @@ class PubServeLayer extends ProxyLayer {
debug: debug,
mapTo: mapTo,
protocol: protocol,
- publicPath: publicPath);
+ publicPath: publicPath,
+ streamToIO: streamToIO != false);
@override
void serve(Router router) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 630d763c..31845d29 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: angel_proxy
description: Angel middleware to forward requests to another server (i.e. pub serve).
-version: 1.0.2
+version: 1.0.3
author: Tobe O
homepage: https://github.com/angel-dart/proxy
environment:
@@ -8,5 +8,7 @@ environment:
dependencies:
angel_framework: ^1.0.0-dev
dev_dependencies:
+ angel_compress: ^1.0.0
+ angel_test: ^1.0.0
http: ^0.11.3
test: ^0.12.15
\ No newline at end of file
diff --git a/test/basic_test.dart b/test/basic_test.dart
index fb954fb5..8e1f02d0 100644
--- a/test/basic_test.dart
+++ b/test/basic_test.dart
@@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_proxy/angel_proxy.dart';
+import 'package:angel_test/angel_test.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';
import 'common.dart';
@@ -24,6 +25,8 @@ main() {
testServer.address.address, testServer.port,
mapTo: '/foo'));
+ app.after.add((req, res) async => res.write('intercept empty'));
+
server = await app.startServer();
url = 'http://${server.address.address}:${server.port}';
});
@@ -41,6 +44,17 @@ main() {
expect(response.body, equals('"world"'));
});
+ test('empty', () async {
+ var response = await client.get('$url/proxy/empty');
+ print('Response: ${response.body}');
+
+ // Shouldn't say it is gzipped...
+ expect(response, isNot(hasHeader('content-encoding')));
+
+ // Should have gzipped body
+ expect(response.body, 'intercept empty');
+ });
+
test('mapTo', () async {
final response = await client.get('$url/bar');
print('Response: ${response.body}');
diff --git a/test/pub_serve_test.dart b/test/pub_serve_test.dart
new file mode 100644
index 00000000..955b89e5
--- /dev/null
+++ b/test/pub_serve_test.dart
@@ -0,0 +1,76 @@
+import 'dart:convert';
+import 'dart:io';
+import 'package:angel_compress/angel_compress.dart';
+import 'package:angel_framework/angel_framework.dart';
+import 'package:angel_proxy/angel_proxy.dart';
+import 'package:angel_test/angel_test.dart';
+import 'package:test/test.dart';
+
+main() {
+ Angel app, testApp;
+ TestClient client;
+
+ setUp(() async {
+ testApp = new Angel();
+ testApp.get('/foo', (req, res) => res.write('pub serve'));
+ testApp.get('/empty', (req, res) => res.end());
+ testApp.responseFinalizers.add(gzip());
+ var server = await testApp.startServer();
+
+ app = new Angel();
+ app.get('/bar', (req, res) => res.write('normal'));
+ var layer = new PubServeLayer(
+ publicPath: '/proxy', host: server.address.address, port: server.port);
+ print('streamToIO: ${layer.streamToIO}');
+ await app.configure(layer);
+
+ app.responseFinalizers.add((req, ResponseContext res) async {
+ print('Normal. Buf: ' +
+ new String.fromCharCodes(res.buffer.toBytes()) +
+ ', headers: ${res.headers}');
+ });
+ app.responseFinalizers.add(gzip());
+
+ client = await connectTo(app);
+ });
+
+ tearDown(() async {
+ await client.close();
+ await app.close();
+ await testApp.close();
+ app = null;
+ testApp = null;
+ });
+
+ test('proxied', () async {
+ var response = await client.get('/proxy/foo');
+
+ // Should say it is gzipped...
+ expect(response, hasHeader('content-encoding', 'gzip'));
+
+ // Should have gzipped body
+ expect(response.body, 'pub serve');
+ });
+
+ test('empty', () async {
+ var response = await client.get('/proxy/empty');
+
+ // Should say it is gzipped...
+ expect(response, hasHeader('content-encoding', 'gzip'));
+
+ // Should have gzipped body
+ expect(response.bodyBytes, isEmpty);
+ });
+
+ test('normal', () async {
+ var response = await client.get('/bar');
+
+ // Should say it is gzipped...
+ expect(response, hasHeader('content-encoding', 'gzip'));
+
+ // Should have normal body
+ //
+ // We have to decode it, because `mock_request` does not auto-decode.
+ expect(UTF8.decode(GZIP.decode(response.bodyBytes)), 'normal');
+ });
+}