Support SSL, HTTP2
This commit is contained in:
parent
d7e96ae616
commit
bbf16acaf5
10 changed files with 214 additions and 202230 deletions
|
@ -22,14 +22,14 @@ import 'dart:isolate';
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:angel_production/angel_production.dart';
|
import 'package:angel_production/angel_production.dart';
|
||||||
|
|
||||||
main(List<String> args) => new Runner('example', configureServer).run(args);
|
main(List<String> args) => Runner('example', configureServer).run(args);
|
||||||
|
|
||||||
Future configureServer(Angel app) async {
|
Future configureServer(Angel app) async {
|
||||||
app.get('/', (req, res) => 'Hello, production world!');
|
app.get('/', (req, res) => 'Hello, production world!');
|
||||||
|
|
||||||
app.get('/crash', (req, res) {
|
app.get('/crash', (req, res) {
|
||||||
// We'll crash this instance deliberately, but the Runner will auto-respawn for us.
|
// We'll crash this instance deliberately, but the Runner will auto-respawn for us.
|
||||||
new Timer(const Duration(seconds: 3), Isolate.current.kill);
|
Timer(const Duration(seconds: 3), Isolate.current.kill);
|
||||||
return 'Crashing in 3s...';
|
return 'Crashing in 3s...';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
29
dev.key
Normal file
29
dev.key
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIIE5DAcBgoqhkiG9w0BDAEBMA4ECL7L6rj6uEHGAgIIAASCBMLbucyfqAkgCbhP
|
||||||
|
xNSHYllPMAv/dsIjtnsBwepCXPGkCBCuOAw/2FaCHjN9hBqL5V7fkrKeaemhm2YE
|
||||||
|
ycPtlHJYPDf3kEkyMjdZ9rIY6kePGfQizs2uJPcXj4YPyQ4HsfVXpOicKfQrouf5
|
||||||
|
Mze9bGzeMN065q3iP4dYUMwHAyZYteXCsanQNHlqvsWli0W+H8St8fdsXefZhnv1
|
||||||
|
qVatKWdNdWQ9t5MuljgNU2Vv56sHKEYXI0yLxk2QUMk8KlJfnmt8foYUsnPUXHmc
|
||||||
|
gIjLKwwVkpdololnEHSNu0cEOUPowjgJru+uMpn7vdNl7TPEQ9jbEgdNg4JwoYzU
|
||||||
|
0nao8WzjaSp7kzvZz0VFwKnk5AjstGvvuAWckADdq23QElbn/mF7AG1m/TBpYxzF
|
||||||
|
gTt37UdndS/AcvVznWVVrRP5iTSIawdIwvqI4s7rqsoE0GCcak+RhchgAz2gWKkS
|
||||||
|
oODUo0JL6pPVbJ3l4ebbaO6c99nDVc8dViPtc1EkStJEJ2O4kI4xgLSCr4Y9ahKn
|
||||||
|
oAaoSkX7Xxq3aQm+BzqSpLjdGL8atsqR/YVOIHYIl3gThvP0NfZGx1xHyvO5mCdZ
|
||||||
|
kHxSA7tKWxauZ3eQ2clbnzeRsl4El0WMHy/5K1ovene4v7sunmoXVtghBC8hK6eh
|
||||||
|
zMO9orex2PNQ/VQC7HCvtytunOVx1lkSBoNo7hR70igg6rW9H7UyoAoBOwMpT1xa
|
||||||
|
J6V62nqruTKOqFNfur7aHJGpHGtDb5/ickHeYCyPTvmGp67u4wChzKReeg02oECe
|
||||||
|
d1E5FKAcIa8s9TVOB6Z+HvTRNQZu2PsI6TJnjQRowvY9DAHiWTlJZBBY/pko3hxX
|
||||||
|
TsIeybpvRdEHpDWv86/iqtw1hv9CUxS/8ZTWUgBo+osShHW79FeDASr9FC4/Zn76
|
||||||
|
ZDERTgV4YWlW/klVWcG2lFo7jix+OPXAB+ZQavLhlN1xdWBcIz1AUWjAM4hdPylW
|
||||||
|
HCX4PB9CQIPl2E7F+Y2p6nMcMWSJVBi5UIH7E9LfaBguXSzMmTk2Fw5p1aOQ6wfN
|
||||||
|
goVAMVwi8ppAVs741PfHdZ295xMmK/1LCxz5DeAdD/tsA/SYfT753GotioDuC7im
|
||||||
|
EyJ5JyvTr5I6RFFBuqt3NlUb3Hp16wP3B2x9DZiB6jxr0l341/NHgsyeBXkuIy9j
|
||||||
|
ON2mvpBPCJhS8kgWo3G0UyyKnx64tcgpGuSvZhGwPz843B6AbYyE6pMRfSWRMkMS
|
||||||
|
YZYa+VNKhR4ixdj07ocFZEWLVjCH7kxkE8JZXKt8jKYmkWd0lS1QVjgaKlO6lRa3
|
||||||
|
q6SPJkhW6pvqobvcqVNXwi1XuzpZeEbuh0B7OTekFTTxx5g9XeDl56M8SVQ1KEhT
|
||||||
|
Q1t7H2Nba18WCB7cf+6PN0F0K0Jz1Kq7ZWaqEI/grX1m4RQuvNF5807sB/QKMO/Z
|
||||||
|
Gz3NXvHg5xTJRd/567lxPGkor0cE7qD1EZfmJ2HrBYXQ91bhgA7LToBuMZo6ZRXH
|
||||||
|
QfsanjbP4FPLMiGdQigLjj3A35L/f4sQOOVac/sRaFnm7pzcxsMvyVU/YtvGcjYE
|
||||||
|
xaOOVnamg661Wo0wksXoDjeSz/JIyyKO3Gwp1FSm2wGLjjy/Ehmqcqy8rvHuf07w
|
||||||
|
AUukhVtTNn4=
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
57
dev.pem
Normal file
57
dev.pem
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDKTCCAhGgAwIBAgIJAOWmjTS+OnTEMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
|
||||||
|
BAMMDGludGVybWVkaWF0ZTAeFw0xNTA1MTgwOTAwNDBaFw0yMzA4MDQwOTAwNDBa
|
||||||
|
MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||||
|
AQoCggEBALlcwQJuzd+xH8QFgfJSn5tRlvhkldSX98cE7NiA602NBbnAVyUrkRXq
|
||||||
|
Ni75lgt0kwjYfA9z674m8WSVbgpLPintPCla9CYky1TH0keIs8Rz6cGWHryWEHiu
|
||||||
|
EDuljQynu2b3sAFuHu9nfWurbJwZnFakBKpdQ9m4EyOZCHC/jHYY7HacKSXg1Cki
|
||||||
|
we2ca0BWDrcqy8kLy0dZ5oC6IZG8O8drAK8f3f44CRYw59D3sOKBrKXaabpvyEcb
|
||||||
|
N7Wk2HDBVwHpUJo1reVwtbM8dhqQayYSD8oXnGpP3RQNu/e2rzlXRyq/BfcDY1JI
|
||||||
|
7TbC4t/7/N4EcPSpGsTcSOC9A7FpzvECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg
|
||||||
|
hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
|
||||||
|
BBYEFCnwiEMMFZh7NhCr+qA8K0w4Q+AOMB8GA1UdIwQYMBaAFB0h1Evsaw2vfrmS
|
||||||
|
YuoCTmC4EE6ZMA0GCSqGSIb3DQEBCwUAA4IBAQAcFmHMaXRxyoNaeOowQ6iQWoZd
|
||||||
|
AUbvG7SHr7I6Pi2aqdqofsKWts7Ytm5WsS0M2nN+sW504houu0iCPeJJX8RQw2q4
|
||||||
|
CCcNOs9IXk+2uMzlpocHpv+yYoUiD5DxgWh7eghQMLyMpf8FX3Gy4VazeuXznHOM
|
||||||
|
4gE4L417xkDzYOzqVTp0FTyAPUv6G2euhNCD6TMru9REcRhYul+K9kocjA5tt2KG
|
||||||
|
MH6y28LXbLyq4YJUxSUU9gY/xlnbbZS48KDqEcdYC9zjW9nQ0qS+XQuQuFIcwjJ5
|
||||||
|
V4kAUYxDu6FoTpyQjgsrmBbZlKNxH7Nj4NDlcdJhp/zeSKHqWa5hSWjjKIxp
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDAjCCAeqgAwIBAgIJAOWmjTS+OnTDMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
|
||||||
|
BAMMDXJvb3RhdXRob3JpdHkwHhcNMTUwNTE4MDkwMDQwWhcNMjMwODA0MDkwMDQw
|
||||||
|
WjAXMRUwEwYDVQQDDAxpbnRlcm1lZGlhdGUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||||
|
DwAwggEKAoIBAQDSrAO1CoPvUllgLOzDm5nG0skDF7vh1DUgAIDVGz0ecD0JFbQx
|
||||||
|
EF79pju/6MbtpTW2FYvRp11t/G7rGtX923ybOHY/1MNFQrdIvPlO1VV7IGKjoMwP
|
||||||
|
DNeb0fIGjHoE9QxaDxR8NX8xQbItpsw+TUtRfc9SLkR+jaYJfVRoM21BOncZbSHE
|
||||||
|
YKiZlEbpecB/+EtwVpgvl+8mPD5U07Fi4fp/lza3WXInXQPyiTVllIEJCt4PKmlu
|
||||||
|
MocNaJOW38bysL7i0PzDpVZtOxLHOTaW68yF3FckIHNCaA7k1ABEEEegjFMmIao7
|
||||||
|
B9w7A0jvr4jZVvNmui5Djjn+oJxwEVVgyf8LAgMBAAGjUDBOMB0GA1UdDgQWBBQd
|
||||||
|
IdRL7GsNr365kmLqAk5guBBOmTAfBgNVHSMEGDAWgBRk81s9d0ZbiZhh44KckwPb
|
||||||
|
oTc0XzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBZQTK0plfdB5PC
|
||||||
|
cC5icut4EmrByJa1RbU7ayuEE70e7hla6KVmVjVdCBGltI4jBYwfhKbRItHiAJ/8
|
||||||
|
x+XZKBG8DLPFuDb7lAa1ObhAYF7YThUFPQYaBhfzKcWrdmWDBFpvNv6E0Mm364dZ
|
||||||
|
e7Yxmbe5S4agkYPoxEzgEYmcUk9jbjdR6eTbs8laG169ljrECXfEU9RiAcqz5iSX
|
||||||
|
NLSewqB47hn3B9qgKcQn+PsgO2j7M+rfklhNgeGJeWmy7j6clSOuCsIjWHU0RLQ4
|
||||||
|
0W3SB/rpEAJ7fgQbYUPTIUNALSOWi/o1tDX2mXPRjBoxqAv7I+vYk1lZPmSzkyRh
|
||||||
|
FKvRDxsW
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDAzCCAeugAwIBAgIJAJ0MomS4Ck+8MA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
|
||||||
|
BAMMDXJvb3RhdXRob3JpdHkwHhcNMTUwNTE4MDkwMDQwWhcNMjMwODA0MDkwMDQw
|
||||||
|
WjAYMRYwFAYDVQQDDA1yb290YXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||||
|
AQ8AMIIBCgKCAQEAts1ijtBV92S2cOvpUMOSTp9c6A34nIGr0T5Nhz6XiqRVT+gv
|
||||||
|
dQgmkdKJQjbvR60y6jzltYFsI2MpGVXY8h/oAL81D/k7PDB2aREgyBfTPAhBHyGw
|
||||||
|
siR+2xYt5b/Zs99q5RdRqQNzNpLPJriIKvUsRyQWy1UiG2s7pRXQeA8qB0XtJdCj
|
||||||
|
kFIi+G2bDsaffspGeDOCqt7t+yqvRXfSES0c/l7DIHaiMbbp4//ZNML3RNgAjPz2
|
||||||
|
hCezZ+wOYajOIyoSPK8IgICrhYFYxvgWxwbLDBEfC5B3jOQsySe10GoRAKZz1gBV
|
||||||
|
DmgReu81tYJmdgkc9zknnQtIFdA0ex+GvZlfWQIDAQABo1AwTjAdBgNVHQ4EFgQU
|
||||||
|
ZPNbPXdGW4mYYeOCnJMD26E3NF8wHwYDVR0jBBgwFoAUZPNbPXdGW4mYYeOCnJMD
|
||||||
|
26E3NF8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEATzkZ97K777uZ
|
||||||
|
lQcduNX3ey4IbCiEzFA2zO5Blj+ilfIwNbZXNOgm/lqNvVGDYs6J1apJJe30vL3X
|
||||||
|
J+t2zsZWzzQzb9uIU37zYemt6m0fHrSrx/iy5lGNqt3HMfqEcOqSCOIK3PCTMz2/
|
||||||
|
uyGe1iw33PVeWsm1JUybQ9IrU/huJjbgOHU4wab+8SJCM49ipArp68Fr6j4lcEaE
|
||||||
|
4rfRg1ZsvxiOyUB3qPn6wyL/JB8kOJ+QCBe498376eaem8AEFk0kQRh6hDaWtq/k
|
||||||
|
t6IIXQLjx+EBDVP/veK0UnVhKRP8YTOoV8ZiG1NcdlJmX/Uk7iAfevP7CkBfSN8W
|
||||||
|
r6AL284qtw==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -4,7 +4,7 @@ import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:angel_production/angel_production.dart';
|
import 'package:angel_production/angel_production.dart';
|
||||||
import 'package:pub_sub/pub_sub.dart' as pub_sub;
|
import 'package:pub_sub/pub_sub.dart' as pub_sub;
|
||||||
|
|
||||||
main(List<String> args) => new Runner('example', configureServer).run(args);
|
main(List<String> args) => Runner('example', configureServer).run(args);
|
||||||
|
|
||||||
Future configureServer(Angel app) async {
|
Future configureServer(Angel app) async {
|
||||||
// Use the injected `pub_sub.Client` to send messages.
|
// Use the injected `pub_sub.Client` to send messages.
|
||||||
|
@ -22,6 +22,11 @@ Future configureServer(Angel app) async {
|
||||||
// Add some routes...
|
// Add some routes...
|
||||||
app.get('/', (req, res) => 'Hello, production world!');
|
app.get('/', (req, res) => 'Hello, production world!');
|
||||||
|
|
||||||
|
app.get('/404', (req, res) {
|
||||||
|
res.statusCode = 404;
|
||||||
|
return res.close();
|
||||||
|
});
|
||||||
|
|
||||||
// Create some routes to demonstrate message passing.
|
// Create some routes to demonstrate message passing.
|
||||||
app.get('/greeting', (req, res) => greeting);
|
app.get('/greeting', (req, res) => greeting);
|
||||||
|
|
||||||
|
@ -35,7 +40,7 @@ Future configureServer(Angel app) async {
|
||||||
// The `Runner` helps with fault tolerance.
|
// The `Runner` helps with fault tolerance.
|
||||||
app.get('/crash', (req, res) {
|
app.get('/crash', (req, res) {
|
||||||
// We'll crash this instance deliberately, but the Runner will auto-respawn for us.
|
// We'll crash this instance deliberately, but the Runner will auto-respawn for us.
|
||||||
new Timer(const Duration(seconds: 3), Isolate.current.kill);
|
Timer(const Duration(seconds: 3), Isolate.current.kill);
|
||||||
return 'Crashing in 3s...';
|
return 'Crashing in 3s...';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
183470
example/main.dill
183470
example/main.dill
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18711
example/main.dill.txt
18711
example/main.dill.txt
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@ import 'dart:io';
|
||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
|
|
||||||
class RunnerOptions {
|
class RunnerOptions {
|
||||||
static final ArgParser argParser = new ArgParser()
|
static final ArgParser argParser = ArgParser()
|
||||||
..addFlag('help',
|
..addFlag('help',
|
||||||
abbr: 'h', help: 'Print this help information.', negatable: false)
|
abbr: 'h', help: 'Print this help information.', negatable: false)
|
||||||
..addFlag('respawn',
|
..addFlag('respawn',
|
||||||
|
@ -11,6 +11,11 @@ class RunnerOptions {
|
||||||
negatable: true)
|
negatable: true)
|
||||||
..addFlag('use-zone',
|
..addFlag('use-zone',
|
||||||
negatable: false, help: 'Create a new Zone for each request.')
|
negatable: false, help: 'Create a new Zone for each request.')
|
||||||
|
..addFlag('quiet', negatable: false, help: 'Completely mute logging.')
|
||||||
|
..addFlag('ssl',
|
||||||
|
negatable: false, help: 'Listen for HTTPS instead of HTTP.')
|
||||||
|
..addFlag('http2',
|
||||||
|
negatable: false, help: 'Listen for HTTP/2 instead of HTTP/1.1.')
|
||||||
..addOption('address',
|
..addOption('address',
|
||||||
abbr: 'a', defaultsTo: '127.0.0.1', help: 'The address to listen on.')
|
abbr: 'a', defaultsTo: '127.0.0.1', help: 'The address to listen on.')
|
||||||
..addOption('concurrency',
|
..addOption('concurrency',
|
||||||
|
@ -18,26 +23,57 @@ class RunnerOptions {
|
||||||
defaultsTo: Platform.numberOfProcessors.toString(),
|
defaultsTo: Platform.numberOfProcessors.toString(),
|
||||||
help: 'The number of isolates to spawn.')
|
help: 'The number of isolates to spawn.')
|
||||||
..addOption('port',
|
..addOption('port',
|
||||||
abbr: 'p', defaultsTo: '3000', help: 'The port to listen on.');
|
abbr: 'p', defaultsTo: '3000', help: 'The port to listen on.')
|
||||||
|
..addOption('certificate-file', help: 'The PEM certificate file to read.')
|
||||||
|
..addOption('certificate-password',
|
||||||
|
help: 'The PEM certificate file password.')
|
||||||
|
..addOption('key-file', help: 'The PEM key file to read.')
|
||||||
|
..addOption('key-password', help: 'The PEM key file password.');
|
||||||
|
|
||||||
final String hostname;
|
final String hostname,
|
||||||
|
certificateFile,
|
||||||
|
keyFile,
|
||||||
|
certificatePassword,
|
||||||
|
keyPassword;
|
||||||
final int concurrency, port;
|
final int concurrency, port;
|
||||||
final bool useZone, respawn;
|
final bool useZone, respawn, quiet, ssl, http2;
|
||||||
|
|
||||||
RunnerOptions(
|
RunnerOptions(
|
||||||
{this.hostname = '127.0.0.1',
|
{this.hostname = '127.0.0.1',
|
||||||
this.port = 3000,
|
this.port = 3000,
|
||||||
this.concurrency = 1,
|
this.concurrency = 1,
|
||||||
this.useZone = false,
|
this.useZone = false,
|
||||||
this.respawn = true});
|
this.respawn = true,
|
||||||
|
this.quiet = false,
|
||||||
|
this.certificateFile,
|
||||||
|
this.keyFile,
|
||||||
|
this.ssl = false,
|
||||||
|
this.http2 = false,
|
||||||
|
this.certificatePassword,
|
||||||
|
this.keyPassword});
|
||||||
|
|
||||||
factory RunnerOptions.fromArgResults(ArgResults argResults) {
|
factory RunnerOptions.fromArgResults(ArgResults argResults) {
|
||||||
return new RunnerOptions(
|
return RunnerOptions(
|
||||||
hostname: argResults['address'] as String,
|
hostname: argResults['address'] as String,
|
||||||
port: int.parse(argResults['port'] as String),
|
port: int.parse(argResults['port'] as String),
|
||||||
concurrency: int.parse(argResults['concurrency'] as String),
|
concurrency: int.parse(argResults['concurrency'] as String),
|
||||||
useZone: argResults['use-zone'] as bool,
|
useZone: argResults['use-zone'] as bool,
|
||||||
respawn: argResults['respawn'] as bool,
|
respawn: argResults['respawn'] as bool,
|
||||||
|
quiet: argResults['quiet'] as bool,
|
||||||
|
certificateFile: argResults.wasParsed('certificate-file')
|
||||||
|
? argResults['certificate-file'] as String
|
||||||
|
: null,
|
||||||
|
keyFile: argResults.wasParsed('key-file')
|
||||||
|
? argResults['key-file'] as String
|
||||||
|
: null,
|
||||||
|
ssl: argResults['ssl'] as bool,
|
||||||
|
http2: argResults['http2'] as bool,
|
||||||
|
certificatePassword: argResults.wasParsed('certificate-password')
|
||||||
|
? argResults['certificate-password'] as String
|
||||||
|
: null,
|
||||||
|
keyPassword: argResults.wasParsed('key-password')
|
||||||
|
? argResults['key-password'] as String
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:isolate';
|
||||||
import 'package:angel_container/angel_container.dart';
|
import 'package:angel_container/angel_container.dart';
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:angel_framework/http.dart';
|
import 'package:angel_framework/http.dart';
|
||||||
|
import 'package:angel_framework/http2.dart';
|
||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
import 'package:io/ansi.dart';
|
import 'package:io/ansi.dart';
|
||||||
import 'package:io/io.dart';
|
import 'package:io/io.dart';
|
||||||
|
@ -73,17 +74,17 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
||||||
///
|
///
|
||||||
/// If respawning is enabled, the [Future] will *never* complete.
|
/// If respawning is enabled, the [Future] will *never* complete.
|
||||||
Future spawnIsolate(int id, RunnerOptions options, SendPort pubSubSendPort) {
|
Future spawnIsolate(int id, RunnerOptions options, SendPort pubSubSendPort) {
|
||||||
return _spawnIsolate(id, new Completer(), options, pubSubSendPort);
|
return _spawnIsolate(id, Completer(), options, pubSubSendPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _spawnIsolate(
|
Future _spawnIsolate(
|
||||||
int id, Completer c, RunnerOptions options, SendPort pubSubSendPort) {
|
int id, Completer c, RunnerOptions options, SendPort pubSubSendPort) {
|
||||||
var onLogRecord = new ReceivePort();
|
var onLogRecord = ReceivePort();
|
||||||
var onExit = new ReceivePort();
|
var onExit = ReceivePort();
|
||||||
var onError = new ReceivePort();
|
var onError = ReceivePort();
|
||||||
var runnerArgs = new _RunnerArgs(name, configureServer, options, reflector,
|
var runnerArgs = _RunnerArgs(name, configureServer, options, reflector,
|
||||||
onLogRecord.sendPort, pubSubSendPort);
|
onLogRecord.sendPort, pubSubSendPort);
|
||||||
var argsWithId = new _RunnerArgsWithId(id, runnerArgs);
|
var argsWithId = _RunnerArgsWithId(id, runnerArgs);
|
||||||
|
|
||||||
Isolate.spawn(isolateMain, argsWithId,
|
Isolate.spawn(isolateMain, argsWithId,
|
||||||
onExit: onExit.sendPort,
|
onExit: onExit.sendPort,
|
||||||
|
@ -97,19 +98,19 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
||||||
onError.listen((msg) {
|
onError.listen((msg) {
|
||||||
if (msg is List) {
|
if (msg is List) {
|
||||||
var e = msg[0], st = StackTrace.fromString(msg[1].toString());
|
var e = msg[0], st = StackTrace.fromString(msg[1].toString());
|
||||||
handleLogRecord(new LogRecord(
|
handleLogRecord(LogRecord(
|
||||||
Level.SEVERE, 'Fatal error', runnerArgs.loggerName, e, st));
|
Level.SEVERE, 'Fatal error', runnerArgs.loggerName, e, st));
|
||||||
} else {
|
} else {
|
||||||
handleLogRecord(new LogRecord(
|
handleLogRecord(
|
||||||
Level.SEVERE, 'Fatal error', runnerArgs.loggerName, msg));
|
LogRecord(Level.SEVERE, 'Fatal error', runnerArgs.loggerName, msg));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onExit.listen((_) {
|
onExit.listen((_) {
|
||||||
if (options.respawn) {
|
if (options.respawn) {
|
||||||
handleLogRecord(new LogRecord(
|
handleLogRecord(LogRecord(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
'Instance #$id at ${new DateTime.now()}. Respawning immediately...',
|
'Instance #$id at ${DateTime.now()} crashed. Respawning immediately...',
|
||||||
runnerArgs.loggerName));
|
runnerArgs.loggerName));
|
||||||
_spawnIsolate(id, c, options, pubSubSendPort);
|
_spawnIsolate(id, c, options, pubSubSendPort);
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,7 +130,15 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var argResults = RunnerOptions.argParser.parse(args);
|
var argResults = RunnerOptions.argParser.parse(args);
|
||||||
var options = new RunnerOptions.fromArgResults(argResults);
|
var options = RunnerOptions.fromArgResults(argResults);
|
||||||
|
|
||||||
|
if (options.ssl || options.http2) {
|
||||||
|
if (options.certificateFile == null) {
|
||||||
|
throw ArgParserException('Missing --certificate-file option.');
|
||||||
|
} else if (options.keyFile == null) {
|
||||||
|
throw ArgParserException('Missing --key-file option.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print(darkGray.wrap(asciiArt.trim() +
|
print(darkGray.wrap(asciiArt.trim() +
|
||||||
'\n\n' +
|
'\n\n' +
|
||||||
|
@ -143,29 +152,30 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
||||||
}
|
}
|
||||||
|
|
||||||
print('Starting `${name}` application...');
|
print('Starting `${name}` application...');
|
||||||
print('Arguments: $args...\n');
|
|
||||||
|
|
||||||
var adapter = new pub_sub.IsolateAdapter();
|
var adapter = pub_sub.IsolateAdapter();
|
||||||
server = new pub_sub.Server([adapter]);
|
server = pub_sub.Server([adapter]);
|
||||||
|
|
||||||
// Register clients
|
// Register clients
|
||||||
for (int i = 0; i < Platform.numberOfProcessors; i++) {
|
for (int i = 0; i < Platform.numberOfProcessors; i++) {
|
||||||
server.registerClient(new pub_sub.ClientInfo('client$i'));
|
server.registerClient(pub_sub.ClientInfo('client$i'));
|
||||||
}
|
}
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
await Future.wait(new List.generate(options.concurrency,
|
await Future.wait(List.generate(options.concurrency,
|
||||||
(id) => spawnIsolate(id, options, adapter.receivePort.sendPort)));
|
(id) => spawnIsolate(id, options, adapter.receivePort.sendPort)));
|
||||||
} on ArgParserException catch (e) {
|
} on ArgParserException catch (e) {
|
||||||
stderr
|
stderr
|
||||||
..writeln(e.message)
|
..writeln(red.wrap(e.message))
|
||||||
..writeln()
|
..writeln()
|
||||||
..writeln('Options:')
|
..writeln(red.wrap('Options:'))
|
||||||
..writeln(RunnerOptions.argParser.usage);
|
..writeln(red.wrap(RunnerOptions.argParser.usage));
|
||||||
exitCode = ExitCode.usage.code;
|
exitCode = ExitCode.usage.code;
|
||||||
} catch (e) {
|
} catch (e, st) {
|
||||||
stderr..writeln('fatal error: $e');
|
stderr
|
||||||
|
..writeln(red.wrap('fatal error: $e'))
|
||||||
|
..writeln(red.wrap(st.toString()));
|
||||||
exitCode = 1;
|
exitCode = 1;
|
||||||
} finally {
|
} finally {
|
||||||
await server?.close();
|
await server?.close();
|
||||||
|
@ -176,37 +186,66 @@ _ ___ | /| / / /_/ / _ /___ _ /___
|
||||||
var args = argsWithId.args;
|
var args = argsWithId.args;
|
||||||
hierarchicalLoggingEnabled = true;
|
hierarchicalLoggingEnabled = true;
|
||||||
|
|
||||||
var zone = Zone.current.fork(specification: new ZoneSpecification(
|
var zone = Zone.current.fork(specification: ZoneSpecification(
|
||||||
print: (self, parent, zone, msg) {
|
print: (self, parent, zone, msg) {
|
||||||
args.loggingSendPort
|
args.loggingSendPort.send(LogRecord(Level.INFO, msg, args.loggerName));
|
||||||
.send(new LogRecord(Level.INFO, msg, args.loggerName));
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
zone.run(() async {
|
zone.run(() async {
|
||||||
var client = new pub_sub.IsolateClient(
|
var client =
|
||||||
'client${argsWithId.id}', args.pubSubSendPort);
|
pub_sub.IsolateClient('client${argsWithId.id}', args.pubSubSendPort);
|
||||||
|
|
||||||
var app = new Angel(reflector: args.reflector)
|
var app = Angel(reflector: args.reflector)
|
||||||
..container.registerSingleton<pub_sub.Client>(client)
|
..container.registerSingleton<pub_sub.Client>(client)
|
||||||
..container.registerSingleton(new InstanceInfo(id: argsWithId.id));
|
..container.registerSingleton(InstanceInfo(id: argsWithId.id));
|
||||||
|
|
||||||
app.shutdownHooks.add((_) => client.close());
|
app.shutdownHooks.add((_) => client.close());
|
||||||
|
|
||||||
await app.configure(args.configureServer);
|
await app.configure(args.configureServer);
|
||||||
|
|
||||||
if (app.logger == null) {
|
if (app.logger == null) {
|
||||||
app.logger = new Logger(args.loggerName)
|
app.logger = Logger(args.loggerName)
|
||||||
..onRecord.listen(Runner.handleLogRecord);
|
..onRecord.listen(Runner.handleLogRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
var http =
|
AngelHttp http;
|
||||||
new AngelHttp.custom(app, startShared, useZone: args.options.useZone);
|
SecurityContext securityContext;
|
||||||
var server =
|
Uri serverUrl;
|
||||||
await http.startServer(args.options.hostname, args.options.port);
|
|
||||||
var url = new Uri(
|
if (args.options.ssl || args.options.http2) {
|
||||||
scheme: 'http', host: server.address.address, port: server.port);
|
securityContext = SecurityContext();
|
||||||
print('Instance #${argsWithId.id} listening at $url');
|
securityContext.useCertificateChain(args.options.certificateFile,
|
||||||
|
password: args.options.certificatePassword);
|
||||||
|
securityContext.usePrivateKey(args.options.keyFile,
|
||||||
|
password: args.options.keyPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.options.ssl) {
|
||||||
|
http = AngelHttp.custom(app, startSharedSecure(securityContext),
|
||||||
|
useZone: args.options.useZone);
|
||||||
|
} else {
|
||||||
|
http =
|
||||||
|
AngelHttp.custom(app, startShared, useZone: args.options.useZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
Driver driver;
|
||||||
|
|
||||||
|
if (args.options.http2) {
|
||||||
|
securityContext.setAlpnProtocols(['h2'], true);
|
||||||
|
var http2 = AngelHttp2.custom(app, securityContext, startSharedHttp2,
|
||||||
|
useZone: args.options.useZone);
|
||||||
|
http2.onHttp1.listen(http.handleRequest);
|
||||||
|
driver = http2;
|
||||||
|
} else {
|
||||||
|
driver = http;
|
||||||
|
}
|
||||||
|
|
||||||
|
await driver.startServer(args.options.hostname, args.options.port);
|
||||||
|
serverUrl = driver.uri;
|
||||||
|
if (args.options.ssl || args.options.http2)
|
||||||
|
serverUrl = serverUrl.replace(scheme: 'https');
|
||||||
|
print('Instance #${argsWithId.id} listening at $serverUrl');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue