port to uri
This commit is contained in:
parent
b5707a5db2
commit
dbb483b953
6 changed files with 79 additions and 38 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,11 @@
|
||||||
|
# 2.1.0
|
||||||
|
- Use `Uri` instead of archaic `host`, `port`, and `mapTo`. Also cleaner + safer + easier.
|
||||||
|
|
||||||
# 2.0.0
|
# 2.0.0
|
||||||
* Updates for Angel 2. Big thanks to @denkuy!
|
|
||||||
|
- Updates for Angel 2. Big thanks to @denkuy!
|
||||||
|
- Use `package:path` for better path resolution.
|
||||||
|
|
||||||
# 1.1.1
|
# 1.1.1
|
||||||
* Removed reference to `io`; now works with HTTP/2. Thanks to @daniel-v!
|
|
||||||
|
- Removed reference to `io`; now works with HTTP/2. Thanks to @daniel-v!
|
||||||
|
|
|
@ -15,12 +15,25 @@ main() async {
|
||||||
// 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(
|
||||||
client,
|
client,
|
||||||
'https://pub.dartlang.org',
|
Uri.parse('https://pub.dartlang.org'),
|
||||||
publicPath: '/pub',
|
publicPath: '/pub',
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
);
|
);
|
||||||
app.all("/pub/*", pubProxy.handleRequest);
|
app.all("/pub/*", pubProxy.handleRequest);
|
||||||
|
|
||||||
|
// Surprise! We can also proxy WebSockets.
|
||||||
|
//
|
||||||
|
// Play around with this at http://www.websocket.org/echo.html.
|
||||||
|
var echoProxy = new Proxy(
|
||||||
|
client,
|
||||||
|
Uri.parse('http://echo.websocket.org'),
|
||||||
|
publicPath: '/echo',
|
||||||
|
timeout: timeout,
|
||||||
|
recoverFromDead: false,
|
||||||
|
recoverFrom404: false,
|
||||||
|
);
|
||||||
|
app.get('/echo', echoProxy.handleRequest);
|
||||||
|
|
||||||
// Pub's HTML assumes that the site's styles, etc. are on the absolute path `/static`.
|
// Pub's HTML assumes that the site's styles, etc. are on the absolute path `/static`.
|
||||||
// This is not the case here. Let's patch that up:
|
// This is not the case here. Let's patch that up:
|
||||||
app.get('/static/*', (RequestContext req, res) {
|
app.get('/static/*', (RequestContext req, res) {
|
||||||
|
@ -30,7 +43,7 @@ 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(
|
||||||
client,
|
client,
|
||||||
'https://dartlang.org',
|
Uri.parse('https://dartlang.org'),
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
recoverFrom404: false,
|
recoverFrom404: false,
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,8 +2,10 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
|
import 'package:angel_framework/http.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||||
final MediaType _fallbackMediaType = MediaType('application', 'octet-stream');
|
final MediaType _fallbackMediaType = MediaType('application', 'octet-stream');
|
||||||
|
@ -16,20 +18,16 @@ class Proxy {
|
||||||
/// 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.
|
||||||
final bool recoverFromDead;
|
final bool recoverFromDead;
|
||||||
final bool recoverFrom404;
|
final bool recoverFrom404;
|
||||||
final String host, mapTo, publicPath;
|
final Uri baseUrl;
|
||||||
final int port;
|
final String publicPath;
|
||||||
final String protocol;
|
|
||||||
|
|
||||||
/// If `null` then no timout is added for requests
|
/// If `null` then no timout is added for requests
|
||||||
final Duration timeout;
|
final Duration timeout;
|
||||||
|
|
||||||
Proxy(
|
Proxy(
|
||||||
this.httpClient,
|
this.httpClient,
|
||||||
this.host, {
|
this.baseUrl, {
|
||||||
this.port,
|
|
||||||
this.mapTo: '/',
|
|
||||||
this.publicPath: '/',
|
this.publicPath: '/',
|
||||||
this.protocol: 'http',
|
|
||||||
this.recoverFromDead: true,
|
this.recoverFromDead: true,
|
||||||
this.recoverFrom404: true,
|
this.recoverFrom404: true,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
|
@ -49,9 +47,11 @@ class Proxy {
|
||||||
var path = req.path.replaceAll(_straySlashes, '');
|
var path = req.path.replaceAll(_straySlashes, '');
|
||||||
|
|
||||||
if (_prefix.isNotEmpty) {
|
if (_prefix.isNotEmpty) {
|
||||||
if (!path.startsWith(_prefix)) return new Future<bool>.value(true);
|
if (!p.isWithin(_prefix, path) && !p.equals(_prefix, path)) {
|
||||||
|
return new Future<bool>.value(true);
|
||||||
|
}
|
||||||
|
|
||||||
path = path.replaceFirst(_prefix, '').replaceAll(_straySlashes, '');
|
path = p.relative(path, from: _prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return servePath(path, req, res);
|
return servePath(path, req, res);
|
||||||
|
@ -62,24 +62,52 @@ class Proxy {
|
||||||
String path, RequestContext req, ResponseContext res) async {
|
String path, RequestContext req, ResponseContext res) async {
|
||||||
http.StreamedResponse rs;
|
http.StreamedResponse rs;
|
||||||
|
|
||||||
final mapping = '$mapTo/$path'.replaceAll(_straySlashes, '');
|
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 &&
|
||||||
|
WebSocketTransformer.isUpgradeRequest(req.rawRequest)) {
|
||||||
|
print('ws!!!');
|
||||||
|
res.detach();
|
||||||
|
print('detached');
|
||||||
|
uri = uri.replace(scheme: uri.scheme == 'https' ? 'wss' : 'ws');
|
||||||
|
print(uri);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var local = await WebSocketTransformer.upgrade(req.rawRequest);
|
||||||
|
print('local!');
|
||||||
|
var remote = await WebSocket.connect(uri.toString());
|
||||||
|
print('remote!');
|
||||||
|
|
||||||
|
dynamic Function(dynamic) log(String type) {
|
||||||
|
return (x) {
|
||||||
|
print('$type: $x');
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
local.map(log('local->remote')).pipe(remote);
|
||||||
|
remote.map(log('local->remote')).pipe(local);
|
||||||
|
return false;
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e,
|
||||||
|
message: 'Could not connect WebSocket', stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<http.StreamedResponse> accessRemote() async {
|
Future<http.StreamedResponse> accessRemote() async {
|
||||||
var url = port == null ? host : '$host:$port';
|
|
||||||
url = url.replaceAll(_straySlashes, '');
|
|
||||||
url = '$url/$mapping';
|
|
||||||
|
|
||||||
if (!url.startsWith(protocol)) url = '$protocol://$url';
|
|
||||||
url = url.replaceAll(_straySlashes, '');
|
|
||||||
|
|
||||||
var headers = <String, String>{
|
var headers = <String, String>{
|
||||||
'host': port == null ? host : '$host:$port',
|
'host': uri.authority,
|
||||||
'x-forwarded-for': req.remoteAddress.address,
|
'x-forwarded-for': req.remoteAddress.address,
|
||||||
'x-forwarded-port': req.uri.port.toString(),
|
'x-forwarded-port': req.uri.port.toString(),
|
||||||
'x-forwarded-host':
|
'x-forwarded-host':
|
||||||
req.headers.host ?? req.headers.value('host') ?? 'none',
|
req.headers.host ?? req.headers.value('host') ?? 'none',
|
||||||
'x-forwarded-proto': protocol,
|
'x-forwarded-proto': uri.scheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
req.headers.forEach((name, values) {
|
req.headers.forEach((name, values) {
|
||||||
|
@ -95,7 +123,7 @@ class Proxy {
|
||||||
body = (await req.parse()).originalBuffer;
|
body = (await req.parse()).originalBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rq = new http.Request(req.method, Uri.parse(url));
|
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 = Utf8Codec(allowMalformed: true);
|
||||||
|
@ -116,10 +144,10 @@ class Proxy {
|
||||||
stackTrace: st,
|
stackTrace: st,
|
||||||
statusCode: 504,
|
statusCode: 504,
|
||||||
message:
|
message:
|
||||||
'Connection to remote host "$host" timed out after ${timeout.inMilliseconds}ms.',
|
'Connection to remote host "$uri" timed out after ${timeout.inMilliseconds}ms.',
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (recoverFromDead) return true;
|
if (recoverFromDead && e is! AngelHttpException) return true;
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +165,7 @@ class Proxy {
|
||||||
e,
|
e,
|
||||||
stackTrace: st,
|
stackTrace: st,
|
||||||
statusCode: 504,
|
statusCode: 504,
|
||||||
message: 'Host "$host" returned a malformed content-type',
|
message: 'Host "$uri" returned a malformed content-type',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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: 2.0.0
|
version: 2.1.0
|
||||||
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:
|
||||||
|
@ -9,6 +9,7 @@ dependencies:
|
||||||
angel_framework: ^2.0.0-alpha
|
angel_framework: ^2.0.0-alpha
|
||||||
http: ^0.12.0
|
http: ^0.12.0
|
||||||
http_parser: ^3.0.0
|
http_parser: ^3.0.0
|
||||||
|
path: ^1.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel_test: ^2.0.0-alpha
|
angel_test: ^2.0.0-alpha
|
||||||
logging:
|
logging:
|
||||||
|
|
|
@ -23,16 +23,10 @@ main() {
|
||||||
|
|
||||||
var proxy1 = new Proxy(
|
var proxy1 = new Proxy(
|
||||||
httpClient,
|
httpClient,
|
||||||
testServer.address.address,
|
new Uri(host: testServer.address.address, port: testServer.port),
|
||||||
port: testServer.port,
|
|
||||||
publicPath: '/proxy',
|
publicPath: '/proxy',
|
||||||
);
|
);
|
||||||
var proxy2 = new Proxy(
|
var proxy2 = new Proxy(httpClient, proxy1.baseUrl.replace(path: '/foo'));
|
||||||
httpClient,
|
|
||||||
testServer.address.address,
|
|
||||||
port: testServer.port,
|
|
||||||
mapTo: '/foo',
|
|
||||||
);
|
|
||||||
|
|
||||||
app.all("/proxy/*", proxy1.handleRequest);
|
app.all("/proxy/*", proxy1.handleRequest);
|
||||||
app.all("*", proxy2.handleRequest);
|
app.all("*", proxy2.handleRequest);
|
||||||
|
|
|
@ -41,8 +41,7 @@ main() {
|
||||||
|
|
||||||
layer = new Proxy(
|
layer = new Proxy(
|
||||||
httpClient,
|
httpClient,
|
||||||
server.address.address,
|
new Uri(host: server.address.address, port: server.port),
|
||||||
port: server.port,
|
|
||||||
publicPath: '/proxy',
|
publicPath: '/proxy',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue