From 84f2fd07f51628fd3c70e4c67f6f8c57131043de Mon Sep 17 00:00:00 2001 From: thosakwe Date: Sat, 22 Apr 2017 14:46:00 -0400 Subject: [PATCH] 1.0.3 --- .analysis-options | 2 + .idea/angel_proxy.iml | 2 +- .idea/runConfigurations/All_Tests.xml | 7 ++ .idea/runConfigurations/Pub_Serve_Tests.xml | 6 ++ README.md | 2 +- lib/src/proxy_layer.dart | 32 +++++++-- lib/src/pub_serve_layer.dart | 4 +- pubspec.yaml | 4 +- test/basic_test.dart | 14 ++++ test/pub_serve_test.dart | 76 +++++++++++++++++++++ 10 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 .analysis-options create mode 100644 .idea/runConfigurations/All_Tests.xml create mode 100644 .idea/runConfigurations/Pub_Serve_Tests.xml create mode 100644 test/pub_serve_test.dart 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'); + }); +}