2.1.0
This commit is contained in:
parent
dbb483b953
commit
327b3996c1
6 changed files with 27 additions and 33 deletions
|
@ -1,6 +1,9 @@
|
||||||
# 2.1.0
|
# 2.1.0
|
||||||
|
|
||||||
- Use `Uri` instead of archaic `host`, `port`, and `mapTo`. Also cleaner + safer + easier.
|
- Use `Uri` instead of archaic `host`, `port`, and `mapTo`. Also cleaner + safer + easier.
|
||||||
|
|
||||||
|
* Enable WebSocket proxying.
|
||||||
|
|
||||||
# 2.0.0
|
# 2.0.0
|
||||||
|
|
||||||
- Updates for Angel 2. Big thanks to @denkuy!
|
- Updates for Angel 2. Big thanks to @denkuy!
|
||||||
|
|
12
README.md
12
README.md
|
@ -3,6 +3,7 @@
|
||||||
[![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. `webdev serve`).
|
Angel middleware to forward requests to another server (i.e. `webdev serve`).
|
||||||
|
Also supports WebSockets.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:angel_proxy/angel_proxy.dart';
|
import 'package:angel_proxy/angel_proxy.dart';
|
||||||
|
@ -14,22 +15,21 @@ main() async {
|
||||||
var client = http.Client();
|
var client = http.Client();
|
||||||
|
|
||||||
// Forward requests instead of serving statically
|
// Forward requests instead of serving statically
|
||||||
var proxy1 = Proxy(client, 'http://localhost:3000');
|
var proxy1 = Proxy(client, Uri.parse('http://localhost:3000'));
|
||||||
// or split: Proxy(client, 'localhost', port: 8080, protocol: 'http');
|
|
||||||
|
|
||||||
// handle all methods (GET, POST, ...)
|
// handle all methods (GET, POST, ...)
|
||||||
app.all('*', proxy.handleRequest);
|
app.fallback(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
|
||||||
Proxy(client, '<host>', publicPath: '/remote');
|
Proxy(client, baseUrl, 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
|
||||||
Proxy(client, '<host>', mapTo: '/path');
|
Proxy(client, baseUrl.replace(path: '/path'));
|
||||||
```
|
```
|
||||||
|
|
||||||
If your app's `keepRawRequestBuffers` is `true`, then request bodies will be forwarded
|
If your app's `keepRawRequestBuffers` is `true`, then request bodies will be forwarded
|
||||||
|
|
|
@ -29,8 +29,6 @@ main() async {
|
||||||
Uri.parse('http://echo.websocket.org'),
|
Uri.parse('http://echo.websocket.org'),
|
||||||
publicPath: '/echo',
|
publicPath: '/echo',
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
recoverFromDead: false,
|
|
||||||
recoverFrom404: false,
|
|
||||||
);
|
);
|
||||||
app.get('/echo', echoProxy.handleRequest);
|
app.get('/echo', echoProxy.handleRequest);
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,13 @@ class Proxy {
|
||||||
this.recoverFrom404: true,
|
this.recoverFrom404: true,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
}) {
|
}) {
|
||||||
|
if (!baseUrl.hasScheme || !baseUrl.hasAuthority)
|
||||||
|
throw new ArgumentError(
|
||||||
|
'Invalid `baseUrl`. URI must have both a scheme and authority.');
|
||||||
if (this.recoverFromDead == null)
|
if (this.recoverFromDead == null)
|
||||||
throw ArgumentError.notNull("recoverFromDead");
|
throw new ArgumentError.notNull("recoverFromDead");
|
||||||
if (this.recoverFrom404 == null)
|
if (this.recoverFrom404 == null)
|
||||||
throw ArgumentError.notNull("recoverFrom404");
|
throw new ArgumentError.notNull("recoverFrom404");
|
||||||
|
|
||||||
_prefix = publicPath?.replaceAll(_straySlashes, '') ?? '';
|
_prefix = publicPath?.replaceAll(_straySlashes, '') ?? '';
|
||||||
}
|
}
|
||||||
|
@ -64,35 +67,18 @@ class Proxy {
|
||||||
|
|
||||||
var uri = baseUrl.replace(path: p.join(baseUrl.path, path));
|
var uri = baseUrl.replace(path: p.join(baseUrl.path, path));
|
||||||
|
|
||||||
print('a $uri');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
print(req is HttpRequestContext &&
|
|
||||||
WebSocketTransformer.isUpgradeRequest(req.rawRequest));
|
|
||||||
|
|
||||||
if (req is HttpRequestContext &&
|
if (req is HttpRequestContext &&
|
||||||
WebSocketTransformer.isUpgradeRequest(req.rawRequest)) {
|
WebSocketTransformer.isUpgradeRequest(req.rawRequest)) {
|
||||||
print('ws!!!');
|
|
||||||
res.detach();
|
res.detach();
|
||||||
print('detached');
|
|
||||||
uri = uri.replace(scheme: uri.scheme == 'https' ? 'wss' : 'ws');
|
uri = uri.replace(scheme: uri.scheme == 'https' ? 'wss' : 'ws');
|
||||||
print(uri);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var local = await WebSocketTransformer.upgrade(req.rawRequest);
|
var local = await WebSocketTransformer.upgrade(req.rawRequest);
|
||||||
print('local!');
|
|
||||||
var remote = await WebSocket.connect(uri.toString());
|
var remote = await WebSocket.connect(uri.toString());
|
||||||
print('remote!');
|
|
||||||
|
|
||||||
dynamic Function(dynamic) log(String type) {
|
local.pipe(remote);
|
||||||
return (x) {
|
remote.pipe(local);
|
||||||
print('$type: $x');
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
local.map(log('local->remote')).pipe(remote);
|
|
||||||
remote.map(log('local->remote')).pipe(local);
|
|
||||||
return false;
|
return false;
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
throw new AngelHttpException(e,
|
throw new AngelHttpException(e,
|
||||||
|
@ -126,7 +112,7 @@ class Proxy {
|
||||||
var rq = new http.Request(req.method, uri);
|
var rq = new http.Request(req.method, uri);
|
||||||
rq.headers.addAll(headers);
|
rq.headers.addAll(headers);
|
||||||
rq.headers['host'] = rq.url.host;
|
rq.headers['host'] = rq.url.host;
|
||||||
rq.encoding = Utf8Codec(allowMalformed: true);
|
rq.encoding = new Utf8Codec(allowMalformed: true);
|
||||||
|
|
||||||
if (body != null) rq.bodyBytes = body;
|
if (body != null) rq.bodyBytes = body;
|
||||||
|
|
||||||
|
@ -157,7 +143,8 @@ class Proxy {
|
||||||
MediaType mediaType;
|
MediaType mediaType;
|
||||||
if (rs.headers.containsKey(HttpHeaders.contentTypeHeader)) {
|
if (rs.headers.containsKey(HttpHeaders.contentTypeHeader)) {
|
||||||
try {
|
try {
|
||||||
mediaType = MediaType.parse(rs.headers[HttpHeaders.contentTypeHeader]);
|
mediaType =
|
||||||
|
new MediaType.parse(rs.headers[HttpHeaders.contentTypeHeader]);
|
||||||
} on FormatException catch (e, st) {
|
} on FormatException catch (e, st) {
|
||||||
if (recoverFromDead) return true;
|
if (recoverFromDead) return true;
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,16 @@ main() {
|
||||||
|
|
||||||
var proxy1 = new Proxy(
|
var proxy1 = new Proxy(
|
||||||
httpClient,
|
httpClient,
|
||||||
new Uri(host: testServer.address.address, port: testServer.port),
|
new Uri(
|
||||||
|
scheme: 'http',
|
||||||
|
host: testServer.address.address,
|
||||||
|
port: testServer.port),
|
||||||
publicPath: '/proxy',
|
publicPath: '/proxy',
|
||||||
);
|
);
|
||||||
|
|
||||||
var proxy2 = new Proxy(httpClient, proxy1.baseUrl.replace(path: '/foo'));
|
var proxy2 = new Proxy(httpClient, proxy1.baseUrl.replace(path: '/foo'));
|
||||||
|
print('Proxy 1 on: ${proxy1.baseUrl}');
|
||||||
|
print('Proxy 2 on: ${proxy2.baseUrl}');
|
||||||
|
|
||||||
app.all("/proxy/*", proxy1.handleRequest);
|
app.all("/proxy/*", proxy1.handleRequest);
|
||||||
app.all("*", proxy2.handleRequest);
|
app.all("*", proxy2.handleRequest);
|
||||||
|
|
|
@ -41,7 +41,7 @@ main() {
|
||||||
|
|
||||||
layer = new Proxy(
|
layer = new Proxy(
|
||||||
httpClient,
|
httpClient,
|
||||||
new Uri(host: server.address.address, port: server.port),
|
new Uri(scheme: 'http', host: server.address.address, port: server.port),
|
||||||
publicPath: '/proxy',
|
publicPath: '/proxy',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue