commit
a1c65849b9
15 changed files with 220 additions and 124 deletions
|
@ -1,5 +1,10 @@
|
|||
# Change Log
|
||||
|
||||
## 8.2.0
|
||||
|
||||
* Add `addResponseHeader` to `AngelHttp` to add headers to HTTP default response
|
||||
* Add `removeResponseHeader` to `AngelHttp` to remove headers from HTTP default response
|
||||
|
||||
## 8.1.1
|
||||
|
||||
* Updated broken image on README.md
|
||||
|
|
|
@ -22,9 +22,6 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
HttpRequestContext, HttpResponseContext> {
|
||||
@override
|
||||
Uri get uri {
|
||||
//if (server == null) {
|
||||
// throw ArgumentError("[AngelHttp] Server instance not intialised");
|
||||
//}
|
||||
return Uri(
|
||||
scheme: 'http', host: server?.address.address, port: server?.port);
|
||||
}
|
||||
|
@ -38,7 +35,7 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
|
||||
/// An instance mounted on a server started by the [serverGenerator].
|
||||
factory AngelHttp.custom(Angel app, ServerGeneratorType serverGenerator,
|
||||
{bool useZone = true}) {
|
||||
{bool useZone = true, Map<String, String> headers = const {}}) {
|
||||
return AngelHttp._(app, serverGenerator, useZone);
|
||||
}
|
||||
|
||||
|
@ -67,15 +64,6 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
return AngelHttp.fromSecurityContext(app, serverContext, useZone: useZone);
|
||||
}
|
||||
|
||||
/// Use [server] instead.
|
||||
//@deprecated
|
||||
//HttpServer get httpServer {
|
||||
//if (server == null) {
|
||||
// throw ArgumentError("[AngelHttp] Server instance not initialised");
|
||||
//}
|
||||
// return server;
|
||||
//}
|
||||
|
||||
Future handleRequest(HttpRequest request) =>
|
||||
handleRawRequest(request, request.response);
|
||||
|
||||
|
@ -88,6 +76,20 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
return await super.close();
|
||||
}
|
||||
|
||||
/// Remove headers from HTTP Response
|
||||
void removeResponseHeader(Map<String, Object> headers) {
|
||||
headers.forEach((key, value) {
|
||||
server?.defaultResponseHeaders.remove(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
/// Add headers to HTTP Response
|
||||
void addResponseHeader(Map<String, Object> headers) {
|
||||
headers.forEach((key, value) {
|
||||
server?.defaultResponseHeaders.add(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future closeResponse(HttpResponse response) => response.close();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel3_framework
|
||||
version: 8.1.1
|
||||
version: 8.2.0
|
||||
description: A high-powered HTTP server extensible framework with dependency injection, routing and much more.
|
||||
homepage: https://angel3-framework.web.app/
|
||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/framework
|
||||
|
|
|
@ -27,6 +27,7 @@ import 'service_map_test.dart' as service_map;
|
|||
import 'services_test.dart' as services;
|
||||
import 'streaming_test.dart' as streaming;
|
||||
import 'view_generator_test.dart' as view_generator;
|
||||
//import 'response_header_test.dart' as response_header;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
/// For running with coverage
|
||||
|
@ -36,6 +37,7 @@ void main() {
|
|||
group('accepts', accepts.main);
|
||||
group('anonymous service', anonymous_service.main);
|
||||
group('body', body.main);
|
||||
//group('response_header', response_header.main);
|
||||
group('controller', controller.main);
|
||||
group('detach', detach.main);
|
||||
group('di', di.main);
|
||||
|
|
58
packages/framework/test/response_header_test.dart
Normal file
58
packages/framework/test/response_header_test.dart
Normal file
|
@ -0,0 +1,58 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:angel3_container/mirrors.dart';
|
||||
import 'package:angel3_framework/angel3_framework.dart';
|
||||
import 'package:angel3_framework/src/http/angel_http.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
late Angel app;
|
||||
late AngelHttp http;
|
||||
late HttpClient client;
|
||||
|
||||
setUp(() async {
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
http = AngelHttp(app);
|
||||
|
||||
await http.startServer();
|
||||
|
||||
var formData = {'id': 100, 'name': 'William'};
|
||||
app.get('/api/v1/user/list', (RequestContext req, res) async {
|
||||
//await req.parseBody();
|
||||
//res.write('Hello, World!');
|
||||
res.json(formData);
|
||||
});
|
||||
|
||||
client = HttpClient();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
client.close();
|
||||
await http.close();
|
||||
});
|
||||
|
||||
test('Remove Response Header', () async {
|
||||
http.removeResponseHeader({'x-frame-options': 'SAMEORIGIN'});
|
||||
|
||||
var request = await client.get('localhost', 3000, '/api/v1/user/list');
|
||||
HttpClientResponse response = await request.close();
|
||||
//print(response.headers);
|
||||
expect(response.headers['x-frame-options'], isNull);
|
||||
}, skip: true);
|
||||
|
||||
test('Add Response Header', () async {
|
||||
http.addResponseHeader({
|
||||
'X-XSRF_TOKEN':
|
||||
'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'
|
||||
});
|
||||
|
||||
var request = await client.get('localhost', 3000, '/api/v1/user/list');
|
||||
HttpClientResponse response = await request.close();
|
||||
//print(response.headers);
|
||||
expect(
|
||||
response.headers['X-XSRF_TOKEN'],
|
||||
equals([
|
||||
'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'
|
||||
]));
|
||||
}, skip: true);
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
# Change Log
|
||||
|
||||
## 8.1.0
|
||||
|
||||
* Updated `vm_service` to 13.0.0
|
||||
* Added configurable HTTP response header
|
||||
|
||||
## 8.0.0
|
||||
|
||||
* Require Dart >= 3.0
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
Supports *hot reloading* of Angel3 servers on file changes. This is faster and more reliable than merely reactively restarting a `Process`. This package only works with the [Angel3 framework](https://pub.dev/packages/angel3_framework).
|
||||
|
||||
**Not recommended to use in production, unless you are specifically intending for a "hot code push" in production..**
|
||||
**Not recommended to use in production, unless you are specifically intending for a "hot code push" in production.**
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -23,11 +23,7 @@ dependencies:
|
|||
|
||||
## Usage
|
||||
|
||||
This package is dependent on the Dart VM service, so you *must* run Dart with the `--observe` (or `--enable-vm-service`) argument!!!
|
||||
|
||||
Usage is fairly simple. Pass a function that creates an `Angel` server, along with a collection of paths to watch, to the `HotReloader` constructor. The rest is history!!!
|
||||
|
||||
The recommended pattern is to only use hot-reloading in your application entry point. Create your `Angel` instance within a separate function, conventionally named `createServer`.
|
||||
This package is dependent on the Dart VM service, so you *must* run Dart with the `--observe` (or `--enable-vm-service`) argument. Usage is fairly simple. Pass a function that creates an `Angel` server, along with a collection of paths to watch, to the `HotReloader` constructor. The recommended pattern is to only use hot-reloading in your application entry point. Create your `Angel` instance within a separate function, conventionally named `createServer`.
|
||||
|
||||
You can watch:
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:glob/glob.dart';
|
|||
import 'package:glob/list_local_fs.dart';
|
||||
import 'package:belatuk_html_builder/elements.dart';
|
||||
import 'package:io/ansi.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:vm_service/vm_service.dart' as vm;
|
||||
import 'package:vm_service/vm_service_io.dart' as vm;
|
||||
|
@ -19,8 +20,6 @@ import 'package:watcher/watcher.dart';
|
|||
|
||||
/// A utility class that watches the filesystem for changes, and starts new instances of an Angel server.
|
||||
class HotReloader {
|
||||
late vm.VmService _client;
|
||||
vm.IsolateRef? _mainIsolate;
|
||||
final StreamController<WatchEvent> _onChange =
|
||||
StreamController<WatchEvent>.broadcast();
|
||||
final List _paths = [];
|
||||
|
@ -28,8 +27,10 @@ class HotReloader {
|
|||
final Queue<HttpRequest> _requestQueue = Queue<HttpRequest>();
|
||||
late HttpServer _io;
|
||||
AngelHttp? _server;
|
||||
Duration? _timeout;
|
||||
late Duration _timeout;
|
||||
late vm.VmService _client;
|
||||
vm.VM? _vmachine;
|
||||
vm.IsolateRef? _mainIsolate;
|
||||
|
||||
/// If `true` (default), then developers can `press 'r' to reload` the application on-the-fly.
|
||||
///
|
||||
|
@ -47,7 +48,7 @@ class HotReloader {
|
|||
///
|
||||
/// If the timeout expires, then the request will be immediately terminated with a `502 Bad Gateway` error.
|
||||
/// Default: `5s`
|
||||
Duration? get timeout => _timeout;
|
||||
Duration get timeout => _timeout;
|
||||
|
||||
/// The Dart VM service host.
|
||||
///
|
||||
|
@ -116,20 +117,22 @@ class HotReloader {
|
|||
Future handleRequest(HttpRequest request) async {
|
||||
if (_server != null) {
|
||||
return await _handle(request);
|
||||
} else if (timeout == null) {
|
||||
_requestQueue.add(request);
|
||||
//} else if (timeout == null) {
|
||||
// _requestQueue.add(request);
|
||||
} else {
|
||||
_requestQueue.add(request);
|
||||
Timer(timeout!, () {
|
||||
Timer(timeout, () {
|
||||
if (_requestQueue.remove(request)) {
|
||||
// Send 502 response
|
||||
sendError(request, HttpStatus.badGateway, '502 Bad Gateway',
|
||||
'Request timed out after ${timeout!.inMilliseconds}ms.');
|
||||
'Request timed out after ${timeout.inMilliseconds}ms.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Logger? get _appLogger => _server?.app.logger;
|
||||
|
||||
Future<AngelHttp> _generateServer() async {
|
||||
var s = await generator();
|
||||
await Future.forEach(s.startupHooks, s.configure);
|
||||
|
@ -138,23 +141,24 @@ class HotReloader {
|
|||
}
|
||||
|
||||
void _logWarning(String msg) {
|
||||
if (_server?.app.logger != null) {
|
||||
_server?.app.logger.warning(msg);
|
||||
if (_appLogger != null) {
|
||||
_appLogger?.warning(msg);
|
||||
} else {
|
||||
print(yellow.wrap('WARNING: $msg'));
|
||||
}
|
||||
}
|
||||
|
||||
void _logInfo(String msg) {
|
||||
if (_server?.app.logger != null) {
|
||||
_server?.app.logger.info(msg);
|
||||
if (_appLogger != null) {
|
||||
_appLogger?.info(msg);
|
||||
} else {
|
||||
print(lightGray.wrap(msg));
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts listening to requests and filesystem events.
|
||||
Future<HttpServer> startServer([address, int? port]) async {
|
||||
Future<HttpServer> startServer(
|
||||
[String address = '127.0.0.1', int port = 3000]) async {
|
||||
var isHot = true;
|
||||
_server = await _generateServer();
|
||||
|
||||
|
@ -185,9 +189,10 @@ class HotReloader {
|
|||
_mainIsolate ??= _vmachine?.isolates?.first;
|
||||
|
||||
if (_vmachine != null) {
|
||||
for (var isolate in _vmachine!.isolates ?? <vm.IsolateRef>[]) {
|
||||
if (isolate.id != null) {
|
||||
await _client.setIsolatePauseMode(isolate.id!,
|
||||
for (var isolate in _vmachine?.isolates ?? <vm.IsolateRef>[]) {
|
||||
var isolateId = isolate.id;
|
||||
if (isolateId != null) {
|
||||
await _client.setIsolatePauseMode(isolateId,
|
||||
exceptionPauseMode: 'None');
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +208,8 @@ class HotReloader {
|
|||
while (_requestQueue.isNotEmpty) {
|
||||
await _handle(_requestQueue.removeFirst());
|
||||
}
|
||||
var server = _io = await HttpServer.bind(address ?? '127.0.0.1', port ?? 0);
|
||||
var server = _io = await HttpServer.bind(address, port);
|
||||
//server.defaultResponseHeaders();
|
||||
server.listen(handleRequest);
|
||||
|
||||
// Print a Flutter-like prompt...
|
||||
|
@ -213,7 +219,7 @@ class HotReloader {
|
|||
|
||||
Uri? observatoryUri;
|
||||
if (isHot) {
|
||||
observatoryUri = await dev.Service.getInfo().then((i) => i.serverUri!);
|
||||
observatoryUri = await dev.Service.getInfo().then((i) => i.serverUri);
|
||||
}
|
||||
|
||||
print(styleBold.wrap(
|
||||
|
@ -260,7 +266,7 @@ class HotReloader {
|
|||
if (ch == $R) {
|
||||
_logInfo('Manually restarting server...\n');
|
||||
await _killServer();
|
||||
await _server!.close();
|
||||
await _server?.close();
|
||||
var addr = _io.address.address;
|
||||
var port = _io.port;
|
||||
await _io.close(force: true);
|
||||
|
@ -359,21 +365,23 @@ class HotReloader {
|
|||
scheduleMicrotask(() async {
|
||||
// Disconnect active WebSockets
|
||||
try {
|
||||
var ws = _server!.app.container.make<AngelWebSocket>();
|
||||
var ws = _server?.app.container.make<AngelWebSocket>();
|
||||
|
||||
for (var client in ws.clients) {
|
||||
try {
|
||||
await client.close();
|
||||
} catch (e) {
|
||||
_logWarning(
|
||||
'Couldn\'t close WebSocket from session #${client.request.session!.id}: $e');
|
||||
if (ws != null) {
|
||||
for (var client in ws.clients) {
|
||||
try {
|
||||
await client.close();
|
||||
} catch (e) {
|
||||
_logWarning(
|
||||
'Couldn\'t close WebSocket from session #${client.request.session?.id}: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// await Future.forEach(
|
||||
// _server.app.shutdownHooks, _server.app.configure);
|
||||
await _server!.app.close();
|
||||
_server!.app.logger.clearListeners();
|
||||
await _server?.app.close();
|
||||
_server?.app.logger.clearListeners();
|
||||
} catch (_) {
|
||||
// Fail silently...
|
||||
}
|
||||
|
@ -387,11 +395,16 @@ class HotReloader {
|
|||
_server = null;
|
||||
|
||||
if (hot) {
|
||||
var report = await _client.reloadSources(_mainIsolate!.id!);
|
||||
var mainIsolateId = _mainIsolate?.id;
|
||||
if (mainIsolateId != null) {
|
||||
var report = await _client.reloadSources(mainIsolateId);
|
||||
|
||||
if (report.success != null) {
|
||||
_logWarning(
|
||||
'Hot reload failed - perhaps some sources have not been generated yet.');
|
||||
if (report.success != null) {
|
||||
_logWarning(
|
||||
'Hot reload failed - perhaps some sources have not been generated yet.');
|
||||
}
|
||||
} else {
|
||||
_logWarning('Hot reload failed - isolate id does not exist.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel3_hot
|
||||
version: 8.0.0
|
||||
version: 8.1.0
|
||||
description: Supports hot reloading/hot code push of Angel3 servers on file changes.
|
||||
homepage: https://angel3-framework.web.app/
|
||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/hot
|
||||
|
@ -13,17 +13,17 @@ dependencies:
|
|||
glob: ^2.1.0
|
||||
io: ^1.0.0
|
||||
path: ^1.8.0
|
||||
vm_service: ^11.6.0
|
||||
vm_service: ^13.0.0
|
||||
watcher: ^1.0.0
|
||||
logging: ^1.2.0
|
||||
dev_dependencies:
|
||||
http: ^1.0.0
|
||||
logging: ^1.2.0
|
||||
lints: ^2.1.0
|
||||
# dependency_overrides:
|
||||
dependency_overrides:
|
||||
# angel3_container:
|
||||
# path: ../container/angel_container
|
||||
# angel3_framework:
|
||||
# path: ../framework
|
||||
angel3_framework:
|
||||
path: ../framework
|
||||
# angel3_http_exception:
|
||||
# path: ../http_exception
|
||||
# angel3_model:
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Change Log
|
||||
|
||||
## 8.1.0
|
||||
|
||||
* Added optional `responseHeaders` and `removeResponseHeaders` to `Runner`
|
||||
|
||||
## 8.0.0
|
||||
|
||||
* Require Dart >= 3.0
|
||||
|
|
|
@ -9,9 +9,7 @@ Helpers for concurrency, message-passing, rotating loggers, and other production
|
|||
|
||||
![Screenshot](angel3-screenshot.png)
|
||||
|
||||
This will become the de-facto way to run Angel3 applications in deployed environments, as it takes care of inter-isolate communication, respawning dead processes, and other housekeeping for you automatically.
|
||||
|
||||
Most users will want to use the `Runner` class.
|
||||
This will become the de-facto way to run Angel3 applications in deployed environments, as it takes care of inter-isolate communication, respawning dead processes, and other housekeeping for you automatically. Most users will want to use the `Runner` class.
|
||||
|
||||
## `Runner`
|
||||
|
||||
|
@ -45,15 +43,11 @@ When combined with `systemd`, deploying Angel3 applications on Linux can be very
|
|||
## Message Passing
|
||||
|
||||
The `Runner` class uses [`belatuk_pub_sub`](<https://pub.dev/packages/belatuk_pub_sub>) to coordinate
|
||||
message passing between isolates.
|
||||
|
||||
When one isolate sends a message, all other isolates will receive the same message, except for the isolate that sent it.
|
||||
|
||||
It is injected into your application's `Container` as `pub_sub.Client`, so you can use it as follows:
|
||||
message passing between isolates. When one isolate sends a message, all other isolates will receive the same message, except for the isolate that sent it. It is injected into your application's `Container` as `pub_sub.Client`, so you can use it as follows:
|
||||
|
||||
```dart
|
||||
// Use the injected `pub_sub.Client` to send messages.
|
||||
var client = app.container.make<pub_sub.Client>();
|
||||
var client = app.container.make<Client>();
|
||||
|
||||
// We can listen for an event to perform some behavior.
|
||||
//
|
||||
|
@ -66,6 +60,34 @@ onGreetingChanged
|
|||
});
|
||||
```
|
||||
|
||||
## Customising Response Header
|
||||
|
||||
Additional parameters can be passed to the `Runner` class to:
|
||||
|
||||
1. Remove headers from HTTP response.
|
||||
2. Add headers to HTTP response.
|
||||
|
||||
For example, the following code snippet removes `X-FRAME-OPTIONS` and adds `X-XSRF_TOKEN` to the response header.
|
||||
|
||||
```dart
|
||||
|
||||
void main(List<String> args) {
|
||||
// Remove 'X-FRAME-OPTIONS'
|
||||
var removeHeader = {'X-FRAME-OPTIONS': 'SAMEORIGIN'};
|
||||
|
||||
// Add 'X-XSRF_TOKEN'
|
||||
var customHeader = {
|
||||
'X-XSRF-TOKEN':
|
||||
'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'
|
||||
};
|
||||
|
||||
Runner('example', configureServer,
|
||||
removeResponseHeaders: removeHeader, responseHeaders: customHeader)
|
||||
.run(args);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Run-time Metadata
|
||||
|
||||
At run-time, you may want to know information about the currently-running instance, for example, which number instance. For this, the `InstanceInfo` class is injected into each instance:
|
||||
|
|
|
@ -2,13 +2,16 @@ import 'dart:async';
|
|||
import 'dart:isolate';
|
||||
import 'package:angel3_framework/angel3_framework.dart';
|
||||
import 'package:angel3_production/angel3_production.dart';
|
||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart';
|
||||
|
||||
void main(List<String> args) => Runner('example', configureServer).run(args);
|
||||
void main(List<String> args) {
|
||||
Runner('example', configureServer).run(args);
|
||||
}
|
||||
|
||||
Future configureServer(Angel app) async {
|
||||
// Use the injected `pub_sub.Client` to send messages.
|
||||
var client = app.container.make<pub_sub.Client>();
|
||||
var client = app.container.make<Client>();
|
||||
|
||||
var greeting = 'Hello! This is the default greeting.';
|
||||
|
||||
// We can listen for an event to perform some behavior.
|
||||
|
|
|
@ -32,13 +32,12 @@ class RunnerOptions {
|
|||
..addOption('key-file', help: 'The PEM key file to read.')
|
||||
..addOption('key-password', help: 'The PEM key file password.');
|
||||
|
||||
final String? hostname,
|
||||
certificateFile,
|
||||
keyFile,
|
||||
certificatePassword,
|
||||
keyPassword;
|
||||
final String hostname;
|
||||
final String? certificateFile, keyFile, certificatePassword, keyPassword;
|
||||
final int concurrency, port;
|
||||
final bool useZone, respawn, quiet, ssl, http2;
|
||||
final Map<String, Object> removeResponseHeaders = {};
|
||||
final Map<String, Object> responseHeaders = {};
|
||||
|
||||
RunnerOptions(
|
||||
{this.hostname = '127.0.0.1',
|
||||
|
@ -56,26 +55,18 @@ class RunnerOptions {
|
|||
|
||||
factory RunnerOptions.fromArgResults(ArgResults argResults) {
|
||||
return RunnerOptions(
|
||||
hostname: argResults['address'] as String?,
|
||||
hostname: argResults['address'] as String,
|
||||
port: int.parse(argResults['port'] as String),
|
||||
concurrency: int.parse(argResults['concurrency'] as String),
|
||||
useZone: argResults['use-zone'] as bool? ?? false,
|
||||
respawn: argResults['respawn'] as bool? ?? true,
|
||||
quiet: argResults['quiet'] as bool? ?? false,
|
||||
certificateFile: argResults.wasParsed('certificate-file')
|
||||
? argResults['certificate-file'] as String?
|
||||
: null,
|
||||
keyFile: argResults.wasParsed('key-file')
|
||||
? argResults['key-file'] as String?
|
||||
: null,
|
||||
certificateFile: argResults['certificate-file'] as String?,
|
||||
keyFile: argResults['key-file'] as String?,
|
||||
ssl: argResults['ssl'] as bool? ?? false,
|
||||
http2: argResults['http2'] as bool? ?? false,
|
||||
certificatePassword: argResults.wasParsed('certificate-password')
|
||||
? argResults['certificate-password'] as String?
|
||||
: null,
|
||||
keyPassword: argResults.wasParsed('key-password')
|
||||
? argResults['key-password'] as String?
|
||||
: null,
|
||||
certificatePassword: argResults['certificate-password'] as String?,
|
||||
keyPassword: argResults['key-password'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart';
|
||||
import 'package:belatuk_pub_sub/isolate.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:angel3_container/angel3_container.dart';
|
||||
import 'package:angel3_framework/angel3_framework.dart';
|
||||
|
@ -10,8 +12,6 @@ import 'package:args/args.dart';
|
|||
import 'package:io/ansi.dart';
|
||||
import 'package:io/io.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:belatuk_pub_sub/isolate.dart' as pub_sub;
|
||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
||||
import 'instance_info.dart';
|
||||
import 'options.dart';
|
||||
|
||||
|
@ -24,35 +24,21 @@ class Runner {
|
|||
final AngelConfigurer configureServer;
|
||||
final Reflector reflector;
|
||||
|
||||
final Map<String, Object> removeResponseHeaders;
|
||||
final Map<String, Object> responseHeaders;
|
||||
|
||||
Runner(this.name, this.configureServer,
|
||||
{this.reflector = const EmptyReflector()});
|
||||
{this.reflector = const EmptyReflector(),
|
||||
this.removeResponseHeaders = const {},
|
||||
this.responseHeaders = const {}});
|
||||
|
||||
static const String asciiArt2 = '''
|
||||
|
||||
___ _ ________________ _____
|
||||
/ | / | / / ____/ ____/ / |__ /
|
||||
/ /| | / |/ / / __/ __/ / / /_ <
|
||||
/ ___ |/ /| / /_/ / /___/ /______/ /
|
||||
/_/ |_/_/ |_/\\____/_____/_____/____/
|
||||
|
||||
''';
|
||||
|
||||
static const String asciiArt = '''
|
||||
static const String _asciiArt = '''
|
||||
|
||||
_ _ _ ____ _____ _ _____
|
||||
/ \\ | \\ | |/ ___| ____| | |___ /
|
||||
/ _ \\ | \\| | | _| _| | | |_ \\
|
||||
/ ___ \\| |\\ | |_| | |___| |___ ___) |
|
||||
/_/ \\_\\_| \\_|\\____|_____|_____|____/
|
||||
''';
|
||||
|
||||
static const String asciiArtOld = '''
|
||||
____________ ________________________
|
||||
___ |__ | / /_ ____/__ ____/__ /
|
||||
__ /| |_ |/ /_ / __ __ __/ __ /
|
||||
_ ___ | /| / / /_/ / _ /___ _ /___
|
||||
/_/ |_/_/ |_/ ____/ /_____/ /_____/
|
||||
|
||||
''';
|
||||
|
||||
static final DateFormat _defaultDateFormat =
|
||||
|
@ -173,11 +159,14 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
|||
|
||||
/// Starts a number of isolates, running identical instances of an Angel application.
|
||||
Future run(List<String> args) async {
|
||||
pub_sub.Server? server;
|
||||
Server? server;
|
||||
|
||||
try {
|
||||
var argResults = RunnerOptions.argParser.parse(args);
|
||||
|
||||
var options = RunnerOptions.fromArgResults(argResults);
|
||||
options.responseHeaders.addAll(responseHeaders);
|
||||
options.removeResponseHeaders.addAll(removeResponseHeaders);
|
||||
|
||||
if (options.ssl || options.http2) {
|
||||
if (options.certificateFile == null) {
|
||||
|
@ -188,7 +177,7 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
|||
}
|
||||
|
||||
print(darkGray.wrap(
|
||||
'$asciiArt\n\nA batteries-included, full-featured, full-stack framework in Dart.\n\nhttps://angel3-framework.web.app\n'));
|
||||
'$_asciiArt\n\nA batteries-included, full-featured, full-stack framework in Dart.\n\nhttps://angel3-framework.web.app\n'));
|
||||
|
||||
if (argResults['help'] == true) {
|
||||
stdout
|
||||
|
@ -199,12 +188,12 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
|||
|
||||
print('Starting `$name` application...');
|
||||
|
||||
var adapter = pub_sub.IsolateAdapter();
|
||||
server = pub_sub.Server([adapter]);
|
||||
var adapter = IsolateAdapter();
|
||||
server = Server([adapter]);
|
||||
|
||||
// Register clients
|
||||
for (var i = 0; i < Platform.numberOfProcessors; i++) {
|
||||
server.registerClient(pub_sub.ClientInfo('client$i'));
|
||||
server.registerClient(ClientInfo('client$i'));
|
||||
}
|
||||
|
||||
server.start();
|
||||
|
@ -240,11 +229,10 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
|||
));
|
||||
|
||||
zone.run(() async {
|
||||
var client =
|
||||
pub_sub.IsolateClient('client${argsWithId.id}', args.pubSubSendPort);
|
||||
var client = IsolateClient('client${argsWithId.id}', args.pubSubSendPort);
|
||||
|
||||
var app = Angel(reflector: args.reflector)
|
||||
..container.registerSingleton<pub_sub.Client>(client)
|
||||
..container.registerSingleton<Client>(client)
|
||||
..container.registerSingleton(InstanceInfo(id: argsWithId.id));
|
||||
|
||||
app.shutdownHooks.add((_) => client.close());
|
||||
|
@ -292,6 +280,13 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
|||
}
|
||||
|
||||
await driver.startServer(args.options.hostname, args.options.port);
|
||||
|
||||
// Only apply the headers to AngelHttp instance
|
||||
if (driver is AngelHttp) {
|
||||
driver.addResponseHeader(args.options.responseHeaders);
|
||||
driver.removeResponseHeader(args.options.removeResponseHeaders);
|
||||
}
|
||||
|
||||
serverUrl = driver.uri;
|
||||
if (args.options.ssl || args.options.http2) {
|
||||
serverUrl = serverUrl.replace(scheme: 'https');
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel3_production
|
||||
version: 8.0.0
|
||||
version: 8.1.0
|
||||
description: Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel3.
|
||||
homepage: https://angel3-framework.web.app
|
||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/production
|
||||
|
@ -7,7 +7,7 @@ environment:
|
|||
sdk: '>=3.0.0 <4.0.0'
|
||||
dependencies:
|
||||
angel3_container: ^8.0.0
|
||||
angel3_framework: ^8.0.0
|
||||
angel3_framework: ^8.2.0
|
||||
belatuk_pub_sub: ^6.0.0
|
||||
args: ^2.4.0
|
||||
io: ^1.0.0
|
||||
|
@ -15,11 +15,11 @@ dependencies:
|
|||
intl: ^0.18.0
|
||||
dev_dependencies:
|
||||
lints: ^2.1.0
|
||||
# dependency_overrides:
|
||||
dependency_overrides:
|
||||
# angel3_container:
|
||||
# path: ../container/angel_container
|
||||
# angel3_framework:
|
||||
# path: ../framework
|
||||
angel3_framework:
|
||||
path: ../framework
|
||||
# angel3_http_exception:
|
||||
# path: ../http_exception
|
||||
# angel3_model:
|
||||
|
|
Loading…
Reference in a new issue