startSecureServer method
Starts 2 HttpServer instances, one HTTP at port
and other HTTPS at securePort
.
- If
checkCertificate
istrue
will check the current certificate.
Implementation
Future<List<HttpServer>> startSecureServer(
Handler handler, Map<String, String> domainsAndEmails,
{int port = 80,
int securePort = 443,
bindingAddress = '0.0.0.0',
int? backlog,
bool shared = false,
bool checkCertificate = true,
bool requestCertificate = true,
bool forceRequestCertificate = false,
bool loadAllHandledDomains = false}) async {
_logInfo(
'Starting server> bindingAddress: $bindingAddress ; port: $port ; domainAndEmails: $domainsAndEmails');
FutureOr<Response> handlerWithChallenge(r) {
final path = r.requestedUri.path;
if (LetsEncrypt.isWellKnownPath(path)) {
if (LetsEncrypt.isACMEPath(path)) {
return processACMEChallengeRequest(r);
} else if (LetsEncrypt.isSelfCheckPath(path)) {
return processSelfCheckRequest(r);
}
}
return handler(r);
}
var server = await serve(handlerWithChallenge, bindingAddress, port,
backlog: backlog, shared: shared);
Future<HttpServer> startSecureServer(SecurityContext securityContext) {
return serve(handlerWithChallenge, bindingAddress, securePort,
securityContext: securityContext, backlog: backlog, shared: shared);
}
HttpServer? secureServer;
var domains = domainsAndEmails.keys.toList();
_logInfo('$certificatesHandler');
_logInfo('Handled domains: ${certificatesHandler.listAllHandledDomains()}');
var securityContext = await certificatesHandler.buildSecurityContext(
domains,
loadAllHandledDomains: loadAllHandledDomains);
_logInfo(
'securityContext[loadAllHandledDomains: $loadAllHandledDomains]: $securityContext');
if (securityContext == null) {
if (!requestCertificate) {
throw StateError(
"No previous SecureContext. Parameter `requestCertificate` is `false`, can't request certificate!");
}
var domainsToCheck = certificatesHandler.listNotHandledDomains(domains);
_logInfo('Requesting certificate for: $domainsToCheck');
for (var domain in domainsToCheck) {
var domainEmail = domainsAndEmails[domain]!;
var ok = await this.requestCertificate(domain, domainEmail);
if (!ok) {
throw StateError("Error requesting certificate!");
}
}
securityContext = await certificatesHandler.buildSecurityContext(domains,
loadAllHandledDomains: loadAllHandledDomains);
if (securityContext == null) {
throw StateError(
"Error loading SecureContext after successful request of certificate for: $domains");
}
_logInfo('Starting secure server> port: $securePort ; domains: $domains');
secureServer = await startSecureServer(securityContext);
} else {
secureServer = await startSecureServer(securityContext);
if (checkCertificate) {
_logInfo('Checking domains certificates: $domains');
var refreshedCertificate = false;
for (var domain in domains) {
var domainEmail = domainsAndEmails[domain]!;
_logInfo('Checking certificate for: $domain');
var checkCertificateStatus = await this.checkCertificate(
domain, domainEmail,
requestCertificate: requestCertificate,
forceRequestCertificate: forceRequestCertificate);
_logInfo('CheckCertificateStatus: $checkCertificateStatus');
if (checkCertificateStatus.isOkRefreshed) {
refreshedCertificate = true;
} else if (checkCertificateStatus.isNotOK) {
throw StateError(
"Certificate check error! Status: $checkCertificateStatus ; domain: $domain");
}
}
if (refreshedCertificate) {
_logWarning('Refreshing SecureContext due new certificate.');
securityContext = await certificatesHandler.buildSecurityContext(
domains,
loadAllHandledDomains: loadAllHandledDomains);
if (securityContext == null) {
throw StateError(
"Error loading SecureContext after successful certificate check for: $domains");
}
_logWarning('Restarting secure server...');
await secureServer.close(force: true);
secureServer = await startSecureServer(securityContext);
}
}
}
return [server, secureServer];
}