commit
9ff915a105
5 changed files with 24 additions and 23 deletions
17
README.md
17
README.md
|
@ -2,7 +2,7 @@
|
||||||
[![Pub](https://img.shields.io/pub/v/angel_proxy.svg)](https://pub.dartlang.org/packages/angel_proxy)
|
[![Pub](https://img.shields.io/pub/v/angel_proxy.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)
|
[![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. `webdev serve`).
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:angel_proxy/angel_proxy.dart';
|
import 'package:angel_proxy/angel_proxy.dart';
|
||||||
|
@ -11,23 +11,26 @@ import 'package:http/http.dart' as http;
|
||||||
main() async {
|
main() async {
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
var client = new http.Client();
|
var client = http.Client();
|
||||||
var proxy = new Proxy(app, client, 'http://localhost:3000');
|
|
||||||
|
|
||||||
// Forward requests instead of serving statically
|
// Forward requests instead of serving statically
|
||||||
app.use(proxy.handleRequest);
|
var proxy1 = Proxy(client, 'http://localhost:3000');
|
||||||
|
// or split: Proxy(client, 'localhost', port: 8080, protocol: 'http');
|
||||||
|
|
||||||
|
// handle all methods (GET, POST, ...)
|
||||||
|
app.all('*', proxy.handleRequest);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also restrict the proxy to serving only from a specific root:
|
You can also restrict the proxy to serving only from a specific root:
|
||||||
```dart
|
```dart
|
||||||
new Proxy(app, client, '<host>', publicPath: '/remote');
|
Proxy(client, '<host>', publicPath: '/remote');
|
||||||
```
|
```
|
||||||
|
|
||||||
Also, you can map requests to a root path on the remote server
|
Also, you can map requests to a root path on the remote server
|
||||||
```dart
|
```dart
|
||||||
new Proxy(app, client, '<host>', mapTo: '/path');
|
Proxy(client, '<host>', mapTo: '/path');
|
||||||
```
|
```
|
||||||
|
|
||||||
If your app's `storeOriginalBuffer` is `true`, then request bodies will be forwarded
|
If your app's `keepRawRequestBuffers` is `true`, then request bodies will be forwarded
|
||||||
as well, if they are not empty. This allows things like POST requests to function.
|
as well, if they are not empty. This allows things like POST requests to function.
|
||||||
|
|
|
@ -14,7 +14,6 @@ main() async {
|
||||||
// Forward any /api requests to pub.
|
// Forward any /api requests to pub.
|
||||||
// By default, if the host throws a 404, the request will fall through to the next handler.
|
// By default, if the host throws a 404, the request will fall through to the next handler.
|
||||||
var pubProxy = new Proxy(
|
var pubProxy = new Proxy(
|
||||||
app,
|
|
||||||
client,
|
client,
|
||||||
'https://pub.dartlang.org',
|
'https://pub.dartlang.org',
|
||||||
publicPath: '/pub',
|
publicPath: '/pub',
|
||||||
|
@ -30,7 +29,6 @@ main() async {
|
||||||
|
|
||||||
// Anything else should fall through to dartlang.org.
|
// Anything else should fall through to dartlang.org.
|
||||||
var dartlangProxy = new Proxy(
|
var dartlangProxy = new Proxy(
|
||||||
app,
|
|
||||||
client,
|
client,
|
||||||
'https://dartlang.org',
|
'https://dartlang.org',
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
|
|
|
@ -11,7 +11,6 @@ final MediaType _fallbackMediaType = MediaType('application', 'octet-stream');
|
||||||
class Proxy {
|
class Proxy {
|
||||||
String _prefix;
|
String _prefix;
|
||||||
|
|
||||||
final Angel app;
|
|
||||||
final http.Client httpClient;
|
final http.Client httpClient;
|
||||||
|
|
||||||
/// If `true` (default), then the plug-in will ignore failures to connect to the proxy, and allow other handlers to run.
|
/// If `true` (default), then the plug-in will ignore failures to connect to the proxy, and allow other handlers to run.
|
||||||
|
@ -25,7 +24,6 @@ class Proxy {
|
||||||
final Duration timeout;
|
final Duration timeout;
|
||||||
|
|
||||||
Proxy(
|
Proxy(
|
||||||
this.app,
|
|
||||||
this.httpClient,
|
this.httpClient,
|
||||||
this.host, {
|
this.host, {
|
||||||
this.port,
|
this.port,
|
||||||
|
@ -69,7 +67,7 @@ class Proxy {
|
||||||
url = url.replaceAll(_straySlashes, '');
|
url = url.replaceAll(_straySlashes, '');
|
||||||
url = '$url/$mapping';
|
url = '$url/$mapping';
|
||||||
|
|
||||||
if (!url.startsWith('http')) url = 'http://$url';
|
if (!url.startsWith(protocol)) url = '$protocol://$url';
|
||||||
url = url.replaceAll(_straySlashes, '');
|
url = url.replaceAll(_straySlashes, '');
|
||||||
|
|
||||||
var headers = <String, String>{
|
var headers = <String, String>{
|
||||||
|
@ -88,7 +86,7 @@ class Proxy {
|
||||||
|
|
||||||
var body;
|
var body;
|
||||||
|
|
||||||
if (req.method != 'GET' && app.keepRawRequestBuffers == true) {
|
if (req.method != 'GET' && req.app.keepRawRequestBuffers == true) {
|
||||||
body = (await req.parse()).originalBuffer;
|
body = (await req.parse()).originalBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,19 +138,24 @@ class Proxy {
|
||||||
mediaType = _fallbackMediaType;
|
mediaType = _fallbackMediaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxiedHeaders = new Map<String, String>.from(rs.headers);
|
/// if [http.Client] does not provide us with a content length
|
||||||
|
/// OR [http.Client] is about to decode the response (bytecount returned by [http.Response].stream != known length)
|
||||||
|
/// then we can not provide a value downstream => set to '-1' for 'unspecified length'
|
||||||
|
var isContentLengthUnknown = rs.contentLength == null ||
|
||||||
|
rs.headers[HttpHeaders.contentEncodingHeader]?.isNotEmpty == true ||
|
||||||
|
rs.headers[HttpHeaders.transferEncodingHeader]?.isNotEmpty == true;
|
||||||
|
|
||||||
|
var proxiedHeaders = new Map<String, String>.from(rs.headers)
|
||||||
|
..remove(HttpHeaders.contentEncodingHeader) // drop, http.Client has decoded
|
||||||
|
..remove(HttpHeaders.transferEncodingHeader) // drop, http.Client has decoded
|
||||||
|
..[HttpHeaders.contentLengthHeader] = "${isContentLengthUnknown ? '-1' : rs.contentLength}";
|
||||||
|
|
||||||
res
|
res
|
||||||
..contentType = mediaType
|
..contentType = mediaType
|
||||||
..statusCode = rs.statusCode
|
..statusCode = rs.statusCode
|
||||||
..headers.addAll(proxiedHeaders);
|
..headers.addAll(proxiedHeaders);
|
||||||
|
|
||||||
var stream = rs.stream;
|
await rs.stream.pipe(res);
|
||||||
|
|
||||||
// [upgrading to dart2] Keeping this workaround as a reference. It's not properly typed for dart2
|
|
||||||
//if (rs.headers[HttpHeaders.contentEncodingHeader] == 'gzip') stream = stream.transform(gzip.encoder);
|
|
||||||
|
|
||||||
await stream.pipe(res);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,12 @@ main() {
|
||||||
testServer = await startTestServer();
|
testServer = await startTestServer();
|
||||||
|
|
||||||
var proxy1 = new Proxy(
|
var proxy1 = new Proxy(
|
||||||
app,
|
|
||||||
httpClient,
|
httpClient,
|
||||||
testServer.address.address,
|
testServer.address.address,
|
||||||
port: testServer.port,
|
port: testServer.port,
|
||||||
publicPath: '/proxy',
|
publicPath: '/proxy',
|
||||||
);
|
);
|
||||||
var proxy2 = new Proxy(
|
var proxy2 = new Proxy(
|
||||||
app,
|
|
||||||
httpClient,
|
httpClient,
|
||||||
testServer.address.address,
|
testServer.address.address,
|
||||||
port: testServer.port,
|
port: testServer.port,
|
||||||
|
|
|
@ -34,7 +34,6 @@ main() {
|
||||||
var httpClient = new http.Client();
|
var httpClient = new http.Client();
|
||||||
|
|
||||||
layer = new Proxy(
|
layer = new Proxy(
|
||||||
app,
|
|
||||||
httpClient,
|
httpClient,
|
||||||
server.address.address,
|
server.address.address,
|
||||||
port: server.port,
|
port: server.port,
|
||||||
|
|
Loading…
Reference in a new issue