This commit is contained in:
thosakwe 2016-11-23 17:03:06 -05:00
parent 074c2f8511
commit a2dfb17586
15 changed files with 313 additions and 1 deletions

44
.gitignore vendored
View file

@ -25,3 +25,47 @@ doc/api/
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
pubspec.lock
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
# Sensitive or high-churn files:
.idea/dataSources/
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

17
.idea/angel_proxy.iml Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/packages" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="application" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="ECMAScript 6" />
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

28
.idea/misc.xml Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>General</id>
</State>
<State>
<id>XPath</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>AngularJS</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
</project>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/angel_proxy.iml" filepath="$PROJECT_DIR$/.idea/angel_proxy.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Basic Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">
<option name="filePath" value="$PROJECT_DIR$/test/basic_test.dart" />
<method />
</configuration>
</component>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

1
.travis.yml Normal file
View file

@ -0,0 +1 @@
language: dart

View file

@ -1,2 +1,24 @@
# angel_proxy
Middleware to forward requests to another server (i.e. pub serve)
![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev-red.svg)
![build status](https://travis-ci.org/angel-dart/proxy.svg?branch=master)
Angel middleware to forward requests to another server (i.e. pub serve).
Based on [this repo](https://github.com/agilord/http_request_proxy).
```dart
import 'package:angel_proxy/angel_proxy.dart';
main() async {
// ...
// Forward requests instead of serving statically
await app.configure(new ProxyLayer('localhost', 3000));
// Or, use one for pub serve.
//
// This automatically deactivates itself if the app is
// in production.
await app.configure(new PubServeLayer());
}
```

4
lib/angel_proxy.dart Normal file
View file

@ -0,0 +1,4 @@
library angel_proxy;
export 'src/proxy_layer.dart';
export 'src/pub_serve_layer.dart';

83
lib/src/proxy_layer.dart Normal file
View file

@ -0,0 +1,83 @@
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
final RegExp _param = new RegExp(r':([A-Za-z0-9_]+)(\((.+)\))?');
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
String _pathify(String path) {
var p = path.replaceAll(_straySlashes, '');
Map<String, String> replace = {};
for (Match match in _param.allMatches(p)) {
if (match[3] != null) replace[match[0]] = ':${match[1]}';
}
replace.forEach((k, v) {
p = p.replaceAll(k, v);
});
return p;
}
class ProxyLayer {
HttpClient _client;
String _prefix;
final bool debug;
final String host, mapTo, publicPath;
final int port;
ProxyLayer(this.host, this.port,
{this.debug: false,
this.mapTo: '/',
this.publicPath: '/',
SecurityContext securityContext}) {
_client = new HttpClient(context: securityContext);
_prefix = publicPath.replaceAll(_straySlashes, '');
}
call(AngelBase app) async => serve(app);
_printDebug(msg) {
if (debug == true) print(msg);
}
void close() => _client.close(force: true);
void serve(Router router) {
_printDebug('Public path prefix: "$_prefix"');
handler(RequestContext req, ResponseContext res) async {
var path = req.path.replaceAll(_straySlashes, '');
return serveFile(path, req, res);
}
router.get('$publicPath/*', handler);
router.get(publicPath, (req, res) => serveFile('', req, res));
}
serveFile(String path, RequestContext req, ResponseContext res) async {
var _path = path;
if (_prefix.isNotEmpty) {
_path = path.replaceAll(new RegExp('^' + _pathify(_prefix)), '');
}
res
..willCloseItself = true
..end();
// Create mapping
final mapping = '$mapTo/$_path'.replaceAll(_straySlashes, '');
final rq = await _client.open(req.method, host, port, mapping);
await rq.addStream(req.io);
final HttpClientResponse rs = await rq.close();
final HttpResponse r = res.io;
r.statusCode = rs.statusCode;
r.headers.contentType = rs.headers.contentType;
await r.addStream(rs);
await r.flush();
await r.close();
}
}

View file

@ -0,0 +1,21 @@
import 'dart:io';
import 'package:angel_route/angel_route.dart';
import 'proxy_layer.dart';
class PubServeLayer extends ProxyLayer {
PubServeLayer(
{bool debug: false,
String host: 'localhost',
String mapTo: '/',
int port: 8888,
String publicPath: '/'})
: super(host, port, debug: debug, mapTo: mapTo, publicPath: publicPath);
@override
void serve(Router router) {
if (Platform.environment['ANGEL_ENV'] == 'production') {
// Auto-deactivate in production ;)
return;
}
}
}

12
pubspec.yaml Normal file
View file

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

43
test/basic_test.dart Normal file
View file

@ -0,0 +1,43 @@
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_proxy/angel_proxy.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';
import 'common.dart';
main() {
Angel app;
http.Client client = new http.Client();
HttpServer server, testServer;
String url;
setUp(() async {
app = new Angel();
testServer = await testApp().startServer();
await app.configure(new ProxyLayer(testServer.address.address, testServer.port, publicPath: '/proxy'));
await app.configure(new ProxyLayer(testServer.address.address, testServer.port, mapTo: '/foo'));
server = await app.startServer();
url = 'http://${server.address.address}:${server.port}';
});
tearDown(() async {
await testServer.close(force: true);
await server.close(force: true);
app = null;
url = null;
});
test('publicPath', () async {
final response = await client.get('$url/proxy/hello');
print('Response: ${response.body}');
expect(response.body, equals('"world"'));
});
test('mapTo', () async {
final response = await client.get('$url/bar');
print('Response: ${response.body}');
expect(response.body, equals('"baz"'));
});
}

10
test/common.dart Normal file
View file

@ -0,0 +1,10 @@
import 'package:angel_framework/angel_framework.dart';
Angel testApp() {
final app = new Angel();
app.get('/hello', 'world');
app.get('/foo/bar', 'baz');
return app;
}