1
1
import express from 'express' ;
2
2
import { createServer } from 'node:http' ;
3
- import Ultraviolet from '@titaniumnetwork-dev/ultraviolet' ;
4
- import { uvPath } from '@titaniumnetwork-dev/ultraviolet/dist' ;
5
- import { join } from 'path' ;
6
- import { hostname } from 'os' ;
3
+ import { publicPath } from 'ultraviolet-static' ;
4
+ import { uvPath } from '@titaniumnetwork-dev/ultraviolet' ;
5
+ import { epoxyPath } from '@mercuryworkshop/epoxy-transport' ;
6
+ import { baremuxPath } from '@mercuryworkshop/bare-mux/node' ;
7
+ import { join } from 'node:path' ;
8
+ import { hostname } from 'node:os' ;
9
+ import wisp from 'wisp-server-node' ;
7
10
8
11
const app = express ( ) ;
9
- const httpServer = createServer ( app ) ;
10
- const port = process . env . PORT || 8080 ;
11
-
12
- // Serve static Ultraviolet files
12
+ // Load our publicPath first and prioritize it over UV.
13
+ app . use ( express . static ( publicPath ) ) ;
14
+ // Load vendor files last.
15
+ // The vendor's uv.config.js won't conflict with our uv.config.js inside the publicPath directory.
13
16
app . use ( '/uv/' , express . static ( uvPath ) ) ;
17
+ app . use ( '/epoxy/' , express . static ( epoxyPath ) ) ;
18
+ app . use ( '/baremux/' , express . static ( baremuxPath ) ) ;
19
+
20
+ // Error for everything else
21
+ app . use ( ( req , res ) => {
22
+ res . status ( 404 ) ;
23
+ res . sendFile ( join ( publicPath , '404.html' ) ) ;
24
+ } ) ;
14
25
15
- // Serve your static frontend files
16
- app . use ( express . static ( 'public' ) ) ;
26
+ const server = createServer ( ) ;
17
27
18
- const uv = new Ultraviolet ( {
19
- prefix : '/service/' ,
20
- bare : '/bare/' ,
21
- encodeUrl : Ultraviolet . codec . xor . encode ,
22
- decodeUrl : Ultraviolet . codec . xor . decode ,
28
+ server . on ( 'request' , ( req , res ) => {
29
+ res . setHeader ( 'Cross-Origin-Opener-Policy' , 'same-origin' ) ;
30
+ res . setHeader ( 'Cross-Origin-Embedder-Policy' , 'require-corp' ) ;
31
+ app ( req , res ) ;
32
+ } ) ;
33
+ server . on ( 'upgrade' , ( req , socket , head ) => {
34
+ if ( req . url . endsWith ( '/wisp/' ) )
35
+ wisp . routeRequest ( req , socket , head ) ;
36
+ else
37
+ socket . end ( ) ;
23
38
} ) ;
24
39
25
- // Generate proxied URL
26
- app . get ( '/generate-proxy-url' , ( req , res ) => {
27
- const serviceUrl = req . query . url ;
28
- if ( serviceUrl ) {
29
- const encodedUrl = uv . encodeUrl ( serviceUrl ) ;
30
- const proxyUrl = `http://${ hostname ( ) } :${ port } /service/${ encodedUrl } ` ;
31
- res . send ( proxyUrl ) ;
32
- } else {
33
- res . status ( 400 ) . send ( 'No URL provided' ) ;
34
- }
40
+ let port = parseInt ( process . env . PORT || '' ) ;
41
+
42
+ if ( isNaN ( port ) ) port = 8080 ;
43
+
44
+ server . on ( 'listening' , ( ) => {
45
+ const address = server . address ( ) ;
46
+
47
+ // by default we are listening on 0.0.0.0 (every interface)
48
+ // we just need to list a few
49
+ console . log ( 'Listening on:' ) ;
50
+ console . log ( `\thttp://localhost:${ address . port } ` ) ;
51
+ console . log ( `\thttp://${ hostname ( ) } :${ address . port } ` ) ;
52
+ console . log (
53
+ `\thttp://${ address . family === 'IPv6' ? `[${ address . address } ]` : address . address
54
+ } :${ address . port } `
55
+ ) ;
35
56
} ) ;
36
57
37
- app . use ( '/service/' , uv . middleware ( ) ) ;
58
+ // https://expressjs.com/en/advanced/healthcheck-graceful-shutdown.html
59
+ process . on ( 'SIGINT' , shutdown ) ;
60
+ process . on ( 'SIGTERM' , shutdown ) ;
61
+
62
+ function shutdown ( ) {
63
+ console . log ( 'SIGTERM signal received: closing HTTP server' ) ;
64
+ server . close ( ) ;
65
+ process . exit ( 0 ) ;
66
+ }
38
67
39
- httpServer . listen ( port , ( ) => {
40
- console . log ( `Ultraviolet Proxy is running on http:// ${ hostname ( ) } : ${ port } ` ) ;
68
+ server . listen ( {
69
+ port,
41
70
} ) ;
0 commit comments