This commit is contained in:
thosakwe 2017-04-01 22:06:27 -04:00
parent acb8745890
commit 4509b88bbb
6 changed files with 50 additions and 24 deletions

View file

@ -1,7 +1,7 @@
# angel_proxy # angel_proxy
[![version 1.0.0](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)](https://pub.dartlang.org/packages/angel_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?branch=master)](https://travis-ci.org/angel-dart/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). Angel middleware to forward requests to another server (i.e. pub serve).
Based on [this repo](https://github.com/agilord/http_request_proxy). Based on [this repo](https://github.com/agilord/http_request_proxy).
@ -22,3 +22,6 @@ main() async {
await app.configure(new PubServeLayer()); await app.configure(new PubServeLayer());
} }
``` ```
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.

View file

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
@ -39,6 +40,7 @@ void copyHeaders(HttpHeaders from, HttpHeaders to) {
} }
class ProxyLayer { class ProxyLayer {
Angel app;
HttpClient _client; HttpClient _client;
String _prefix; String _prefix;
final bool debug; final bool debug;
@ -56,7 +58,7 @@ class ProxyLayer {
_prefix = publicPath.replaceAll(_straySlashes, ''); _prefix = publicPath.replaceAll(_straySlashes, '');
} }
call(Angel app) async => serve(app); call(Angel app) async => serve(this.app = app);
_printDebug(msg) { _printDebug(msg) {
if (debug == true) print(msg); if (debug == true) print(msg);
@ -69,11 +71,10 @@ class ProxyLayer {
handler(RequestContext req, ResponseContext res) async { handler(RequestContext req, ResponseContext res) async {
var path = req.path.replaceAll(_straySlashes, ''); var path = req.path.replaceAll(_straySlashes, '');
return serveFile(path, req, res); return serveFile(path, req, res);
} }
router.get('$publicPath/*', handler); router.all('$publicPath/*', handler);
} }
serveFile(String path, RequestContext req, ResponseContext res) async { serveFile(String path, RequestContext req, ResponseContext res) async {
@ -83,10 +84,6 @@ class ProxyLayer {
_path = path.replaceAll(new RegExp('^' + _pathify(_prefix)), ''); _path = path.replaceAll(new RegExp('^' + _pathify(_prefix)), '');
} }
res
..willCloseItself = true
..end();
// Create mapping // Create mapping
_printDebug('Serving path $_path via proxy'); _printDebug('Serving path $_path via proxy');
final mapping = '$mapTo/$_path'.replaceAll(_straySlashes, ''); final mapping = '$mapTo/$_path'.replaceAll(_straySlashes, '');
@ -107,16 +104,26 @@ class ProxyLayer {
..set('X-Forwarded-Proto', protocol); ..set('X-Forwarded-Proto', protocol);
_printDebug('Added X-Forwarded headers'); _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 HttpClientResponse rs = await rq.close();
final HttpResponse r = res.io;
_printDebug( _printDebug(
'Proxy responded to $mapping with status code ${rs.statusCode}'); 'Proxy responded to $mapping with status code ${rs.statusCode}');
r.statusCode = rs.statusCode;
r.headers.contentType = rs.headers.contentType; res
copyHeaders(rs.headers, r.headers); ..statusCode = rs.statusCode
await r.addStream(rs); ..contentType = rs.headers.contentType;
await r.flush();
await r.close(); rs.headers.forEach((k, v) {
res.headers[k] = v.join(',');
});
await rs.forEach(res.buffer.add);
res.end();
return false;
} }
} }

View file

@ -18,7 +18,7 @@ class PubServeLayer extends ProxyLayer {
@override @override
void serve(Router router) { void serve(Router router) {
if (Platform.environment['ANGEL_ENV'] == 'production') { if (app?.isProduction == true) {
// Auto-deactivate in production ;) // Auto-deactivate in production ;)
return; return;
} }

View file

@ -1,10 +1,10 @@
name: angel_proxy name: angel_proxy
description: Angel middleware to forward requests to another server (i.e. pub serve). description: Angel middleware to forward requests to another server (i.e. pub serve).
version: 1.0.0 version: 1.0.1
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/proxy homepage: https://github.com/angel-dart/proxy
environment: environment:
sdk: ">=1.18.0" sdk: ">=1.19.0"
dependencies: dependencies:
angel_framework: ^1.0.0-dev angel_framework: ^1.0.0-dev
dev_dependencies: dev_dependencies:

View file

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
import 'package:angel_proxy/angel_proxy.dart'; import 'package:angel_proxy/angel_proxy.dart';
@ -12,7 +13,7 @@ main() {
String url; String url;
setUp(() async { setUp(() async {
app = new Angel(); app = new Angel()..storeOriginalBuffer = true;
testServer = await testApp().startServer(); testServer = await testApp().startServer();
@ -45,4 +46,13 @@ main() {
print('Response: ${response.body}'); print('Response: ${response.body}');
expect(response.body, equals('"baz"')); 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'});
});
} }

View file

@ -5,6 +5,12 @@ Angel testApp() {
app.get('/hello', 'world'); app.get('/hello', 'world');
app.get('/foo/bar', 'baz'); app.get('/foo/bar', 'baz');
app.post('/body', (req, res) => req.lazyBody());
return app; app.fatalErrorStream.listen((e) {
print('FATAL IN TEST APP: ${e.error}');
print(e.stack);
});
return app..dumpTree();
} }