diff --git a/README.md b/README.md index a78aaaf3..784203b9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # angel_proxy -[![version 1.0.0](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)](https://pub.dartlang.org/packages/angel_proxy) -[![build status](https://travis-ci.org/angel-dart/proxy.svg?branch=master)](https://travis-ci.org/angel-dart/proxy) +[![version 1.0.1](https://img.shields.io/badge/version-1.0.1-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). Based on [this repo](https://github.com/agilord/http_request_proxy). @@ -21,4 +21,7 @@ main() async { // in production. await app.configure(new PubServeLayer()); } -``` \ No newline at end of file +``` + +If your app's `storeOriginalBuffer` is `true`, then request bodies will be forwarded +as well, if they are not empty. This allows things like POST requests to function. \ No newline at end of file diff --git a/lib/src/proxy_layer.dart b/lib/src/proxy_layer.dart index 444180ab..28613a89 100644 --- a/lib/src/proxy_layer.dart +++ b/lib/src/proxy_layer.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:angel_framework/angel_framework.dart'; @@ -39,6 +40,7 @@ void copyHeaders(HttpHeaders from, HttpHeaders to) { } class ProxyLayer { + Angel app; HttpClient _client; String _prefix; final bool debug; @@ -56,7 +58,7 @@ class ProxyLayer { _prefix = publicPath.replaceAll(_straySlashes, ''); } - call(Angel app) async => serve(app); + call(Angel app) async => serve(this.app = app); _printDebug(msg) { if (debug == true) print(msg); @@ -69,11 +71,10 @@ class ProxyLayer { handler(RequestContext req, ResponseContext res) async { var path = req.path.replaceAll(_straySlashes, ''); - return serveFile(path, req, res); } - router.get('$publicPath/*', handler); + router.all('$publicPath/*', handler); } serveFile(String path, RequestContext req, ResponseContext res) async { @@ -83,10 +84,6 @@ class ProxyLayer { _path = path.replaceAll(new RegExp('^' + _pathify(_prefix)), ''); } - res - ..willCloseItself = true - ..end(); - // Create mapping _printDebug('Serving path $_path via proxy'); final mapping = '$mapTo/$_path'.replaceAll(_straySlashes, ''); @@ -107,16 +104,26 @@ class ProxyLayer { ..set('X-Forwarded-Proto', protocol); _printDebug('Added X-Forwarded headers'); - await rq.addStream(req.io); + if (app.storeOriginalBuffer == true) { + await req.parse(); + if (req.originalBuffer?.isNotEmpty == true) rq.add(req.originalBuffer); + } + + await rq.flush(); final HttpClientResponse rs = await rq.close(); - final HttpResponse r = res.io; _printDebug( 'Proxy responded to $mapping with status code ${rs.statusCode}'); - r.statusCode = rs.statusCode; - r.headers.contentType = rs.headers.contentType; - copyHeaders(rs.headers, r.headers); - await r.addStream(rs); - await r.flush(); - await r.close(); + + res + ..statusCode = rs.statusCode + ..contentType = rs.headers.contentType; + + rs.headers.forEach((k, v) { + res.headers[k] = v.join(','); + }); + + await rs.forEach(res.buffer.add); + res.end(); + return false; } } diff --git a/lib/src/pub_serve_layer.dart b/lib/src/pub_serve_layer.dart index dd8d1789..33875633 100644 --- a/lib/src/pub_serve_layer.dart +++ b/lib/src/pub_serve_layer.dart @@ -18,7 +18,7 @@ class PubServeLayer extends ProxyLayer { @override void serve(Router router) { - if (Platform.environment['ANGEL_ENV'] == 'production') { + if (app?.isProduction == true) { // Auto-deactivate in production ;) return; } diff --git a/pubspec.yaml b/pubspec.yaml index ba4f2c8a..9369edd9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: angel_proxy description: Angel middleware to forward requests to another server (i.e. pub serve). -version: 1.0.0 +version: 1.0.1 author: Tobe O homepage: https://github.com/angel-dart/proxy environment: - sdk: ">=1.18.0" + sdk: ">=1.19.0" dependencies: angel_framework: ^1.0.0-dev dev_dependencies: diff --git a/test/basic_test.dart b/test/basic_test.dart index 1dcba888..fb954fb5 100644 --- a/test/basic_test.dart +++ b/test/basic_test.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_proxy/angel_proxy.dart'; @@ -12,7 +13,7 @@ main() { String url; setUp(() async { - app = new Angel(); + app = new Angel()..storeOriginalBuffer = true; testServer = await testApp().startServer(); @@ -45,4 +46,13 @@ main() { print('Response: ${response.body}'); expect(response.body, equals('"baz"')); }); + + test('original buffer', () async { + var response = await client.post('$url/proxy/body', + body: {'foo': 'bar'}, + headers: {'content-type': 'application/x-www-form-urlencoded'}); + print('Response: ${response.body}'); + expect(response.body, isNotEmpty); + expect(JSON.decode(response.body), {'foo': 'bar'}); + }); } diff --git a/test/common.dart b/test/common.dart index 734fcf4c..485a87ff 100644 --- a/test/common.dart +++ b/test/common.dart @@ -5,6 +5,12 @@ Angel testApp() { app.get('/hello', 'world'); app.get('/foo/bar', 'baz'); + app.post('/body', (req, res) => req.lazyBody()); - return app; -} \ No newline at end of file + app.fatalErrorStream.listen((e) { + print('FATAL IN TEST APP: ${e.error}'); + print(e.stack); + }); + + return app..dumpTree(); +}