@@ -16,6 +16,7 @@ import js.Node.__dirname;
1616import js .Node .process ;
1717import js .node .Crypto ;
1818import js .node .Http ;
19+ import js .node .Https ;
1920import js .node .http .IncomingMessage ;
2021import js .node .url .URL ;
2122import js .npm .ws .Server as WSServer ;
@@ -159,16 +160,33 @@ class Main {
159160 preparePort ();
160161 }
161162
163+ function isDefaultPort (): Bool {
164+ return port == 80 || port == 443 ;
165+ }
166+
167+ function getPort (protocol : String ): Int {
168+ if (! isDefaultPort ()) return port ;
169+ return switch protocol {
170+ case " https" : 443 ;
171+ case " http" , _ : 80 ;
172+ }
173+ }
174+
162175 function runServer (): Void {
163- trace (' Local: http:// $localIp : $port ' );
176+ final ssl = getSslConfig (config );
177+ final protocol = ssl == null ? " http" : " https" ;
178+ final port = getPort (protocol );
179+ final colonPort = isDefaultPort () ? " " : ' : $port ' ;
180+
181+ trace (' Local: $protocol :// $localIp $colonPort ' );
164182 if (config .localNetworkOnly ) {
165183 trace (" Global network is disabled in config" );
166184 } else {
167185 if (! isNoState ) Utils .getGlobalIp (ip -> {
168186 final isIp6 = ip .contains (" :" );
169187 if (isIp6 ) ip = ' [ $ip ]' ;
170188 globalIp = ip ;
171- trace (' Global: http :// $globalIp : $ port ' );
189+ trace (' Global: $ protocol :// $globalIp $ colonPort ' );
172190 });
173191 }
174192
@@ -181,10 +199,26 @@ class Main {
181199 });
182200 Lang .init (' $dir /langs' );
183201
184- final server = Http .createServer ((req , res ) -> {
185- httpServer .serveFiles (req , res );
186- });
187- wss = new WSServer ({server : server });
202+ final server = if (ssl == null ) {
203+ Http .createServer (httpServer .serveFiles );
204+ } else {
205+ if (isDefaultPort ()) {
206+ try {
207+ final redirectHttpServer = Http .createServer ((req , res ) -> {
208+ final host = req .headers [" host" ] ?? " " ;
209+ final location = ' https:// $host ${req .url }' ;
210+ res .writeHead (302 , {" location" : location });
211+ res .end ();
212+ });
213+ redirectHttpServer .listen (80 );
214+ } catch (e ) {
215+ trace (" Cannot run http server on port 80 for https redirects:" , e );
216+ }
217+ }
218+
219+ Https .createServer ({key : ssl .key , cert : ssl .cert }, httpServer .serveFiles );
220+ }
221+ wss = new WSServer ({server : cast server });
188222 wss .on (" connection" , onConnect );
189223 if (config .localNetworkOnly ) server .listen (port , localIp , onServerInited );
190224 else server .listen (port , onServerInited );
@@ -201,6 +235,27 @@ class Main {
201235 };
202236 }
203237
238+ function getSslConfig (config : Config ): Null <{key : String , cert : String }> {
239+ final c = config ;
240+ if (c .sslKeyPemPath .length == 0 && c .sslCertPemPath .length == 0 ) return null ;
241+ final hasBoth = FileSystem .exists (c .sslKeyPemPath )
242+ && FileSystem .exists (c .sslCertPemPath );
243+ if (hasBoth ) {
244+ final key = File .getContent (c .sslKeyPemPath );
245+ final cert = File .getContent (c .sslCertPemPath );
246+ return {
247+ key : key ,
248+ cert : cert
249+ }
250+ }
251+
252+ if (! FileSystem .exists (c .sslKeyPemPath ))
253+ trace (' sslKeyPemPath: absolute file path not found: ${c .sslKeyPemPath }' );
254+ if (! FileSystem .exists (c .sslCertPemPath ))
255+ trace (' sslCertPemPath: absolute file path not found: ${c .sslCertPemPath }' );
256+ return null ;
257+ }
258+
204259 dynamic function onServerInited (): Void {};
205260
206261 public function exit (): Void {
0 commit comments