@@ -12,9 +12,7 @@ import cheerio from 'cheerio';
12
12
* Validating the incoming host should help prevent abuse by restricting
13
13
* the passed host header to the allowedHosts list.
14
14
*/
15
- const allowedHosts = new Set ( [
16
- '83c5-2600-1700-f2e0-b0f-74f7-c2c1-a4ad-e69d.ngrok-free.app' ,
17
- ] ) ;
15
+ const allowedHosts = new Set ( [ '83c5-2600-1700-f2e0-b0f-74f7-c2c1-a4ad-e69d.ngrok-free.app' ] ) ;
18
16
19
17
/**
20
18
* @typedef {Object } ExtensionOptions - The configuration options for the extension.
@@ -31,14 +29,10 @@ const allowedHosts = new Set([
31
29
* @param {string } expectedType The expected type (i.e. `'string'`, `'number'`, `'boolean'`, etc.).
32
30
*/
33
31
function assertType ( name , option , expectedType ) {
34
- if ( option ) {
35
- const found = typeof option ;
36
- assert . strictEqual (
37
- found ,
38
- expectedType ,
39
- `${ name } must be type ${ expectedType } . Received: ${ found } `
40
- ) ;
41
- }
32
+ if ( option ) {
33
+ const found = typeof option ;
34
+ assert . strictEqual ( found , expectedType , `${ name } must be type ${ expectedType } . Received: ${ found } ` ) ;
35
+ }
42
36
}
43
37
44
38
/**
@@ -47,114 +41,115 @@ function assertType(name, option, expectedType) {
47
41
* @returns {Required<ExtensionOptions> }
48
42
*/
49
43
function resolveConfig ( options ) {
50
- assertType ( 'port' , options . port , 'number' ) ;
51
- assertType ( 'subPath' , options . subPath , 'string' ) ;
52
-
53
- // Remove leading and trailing slashes from subPath
54
- if ( options . subPath ?. [ 0 ] === '/' ) {
55
- options . subPath = options . subPath . slice ( 1 ) ;
56
- }
57
- if ( options . subPath ?. [ options . subPath ?. length - 1 ] === '/' ) {
58
- options . subPath = options . subPath . slice ( 0 , - 1 ) ;
59
- }
60
-
61
- return {
62
- port : options . port ?? 3000 ,
63
- subPath : options . subPath ?? '' ,
64
- servers : options . servers ,
65
- } ;
44
+ assertType ( 'port' , options . port , 'number' ) ;
45
+ assertType ( 'subPath' , options . subPath , 'string' ) ;
46
+
47
+ // Remove leading and trailing slashes from subPath
48
+ if ( options . subPath ?. [ 0 ] === '/' ) {
49
+ options . subPath = options . subPath . slice ( 1 ) ;
50
+ }
51
+ if ( options . subPath ?. [ options . subPath ?. length - 1 ] === '/' ) {
52
+ options . subPath = options . subPath . slice ( 0 , - 1 ) ;
53
+ }
54
+
55
+ return {
56
+ port : options . port ?? 3000 ,
57
+ subPath : options . subPath ?? '' ,
58
+ servers : options . servers ,
59
+ } ;
66
60
}
67
61
68
62
/**
69
63
* Start the Express.js server and configure it to integrate with `options.servers.http`.
70
64
* @param {ExtensionOptions } options
71
65
*/
72
66
export function start ( options = { } ) {
73
- const config = resolveConfig ( options ) ;
74
-
75
- return {
76
- async handleDirectory ( _ , componentPath ) {
77
- console . log ( `Setting up Express.js app in ${ componentPath } ` ) ;
78
-
79
- if (
80
- ! fs . existsSync ( componentPath ) ||
81
- ! fs . statSync ( componentPath ) . isDirectory ( )
82
- ) {
83
- throw new Error ( `Invalid component path: ${ componentPath } ` ) ;
84
- }
85
-
86
- const app = express ( ) ;
87
-
88
- // Middleware to validate host
89
- app . use ( ( req , res , next ) => {
90
- const host = req . headers [ 'x-forwarded-host' ] || req . hostname ;
91
- if ( ! allowedHosts . has ( host ) ) {
92
- console . error ( `Rejected request from unauthorized host: ${ host } ` ) ;
93
- return res . status ( 403 ) . send ( 'Forbidden' ) ;
94
- }
95
- next ( ) ;
96
- } ) ;
97
-
98
- // Middleware for proxying and DOM manipulation
99
- app . use (
100
- proxy ( 'https://example.com' , {
101
- proxyReqPathResolver : ( req ) => req . url ,
102
- userResDecorator : async ( proxyRes , proxyResData , req , res ) => {
103
- const contentType = proxyRes . headers [ 'content-type' ] || '' ;
104
- if ( contentType . includes ( 'text/html' ) ) {
105
- const $ = cheerio . load ( proxyResData . toString ( 'utf-8' ) ) ;
106
- // Example DOM manipulation
107
- $ ( 'title' ) . text ( 'Modified Title' ) ;
108
- return $ . html ( ) ;
109
- }
110
- return proxyResData ;
111
- } ,
112
- } )
113
- ) ;
114
-
115
- // Middleware for static files
116
- const staticPath = path . join ( componentPath , 'public' ) ;
117
- if ( fs . existsSync ( staticPath ) ) {
118
- app . use ( express . static ( staticPath ) ) ;
119
- console . log ( `Serving static files from: ${ staticPath } ` ) ;
120
- }
121
-
122
- // Middleware for subPath handling
123
- // app.use((req, res, next) => {
124
- // if (config.subPath && !req.url.startsWith(`/${config.subPath}/`)) {
125
- // return next(); // Not a matching path; skip handling
126
- // }
127
-
128
- // // Rewrite the URL to remove the subPath prefix
129
- // req.url = config.subPath
130
- // ? req.url.replace(new RegExp(`^/${config.subPath}/`), '/')
131
- // : req.url;
132
-
133
- // next();
134
- // });
135
-
136
- // Hook into `options.servers.http`
137
- config . servers . http ( async ( request , nextHandler ) => {
138
- const { _nodeRequest : req , _nodeResponse : res } = request ;
139
-
140
- app . handle ( req , res , ( err ) => {
141
- if ( err ) {
142
- console . error ( `Error handling request: ${ err . message } ` ) ;
143
- res . statusCode = 500 ;
144
- res . end ( 'Internal Server Error' ) ;
145
- } else {
146
- nextHandler ( request ) ;
147
- }
148
- } ) ;
149
- } ) ;
150
-
151
- // Start the Express server
152
- const port = config . port ;
153
- app . listen ( port , ( ) => {
154
- console . log ( `Express.js server is running on port ${ port } ` ) ;
155
- } ) ;
156
-
157
- return true ;
158
- } ,
159
- } ;
67
+ const config = resolveConfig ( options ) ;
68
+
69
+ return {
70
+ async handleDirectory ( _ , componentPath ) {
71
+ console . log ( `Setting up Express.js app in ${ componentPath } ` ) ;
72
+
73
+ if ( ! fs . existsSync ( componentPath ) || ! fs . statSync ( componentPath ) . isDirectory ( ) ) {
74
+ throw new Error ( `Invalid component path: ${ componentPath } ` ) ;
75
+ }
76
+
77
+ const app = express ( ) ;
78
+
79
+ app . use ( ( req , res , next ) => {
80
+ return res . status ( 200 ) . send ( `Hello World from ${ req . url } ` ) ;
81
+ } ) ;
82
+
83
+ // // Middleware to validate host
84
+ // app.use((req, res, next) => {
85
+ // const host = req.headers['x-forwarded-host'] || req.hostname;
86
+ // if (!allowedHosts.has(host)) {
87
+ // console.error(`Rejected request from unauthorized host: ${host}`);
88
+ // return res.status(403).send('Forbidden');
89
+ // }
90
+ // next();
91
+ // });
92
+
93
+ // // Middleware for proxying and DOM manipulation
94
+ // app.use(
95
+ // proxy('https://example.com', {
96
+ // proxyReqPathResolver: (req) => req.url,
97
+ // userResDecorator: async (proxyRes, proxyResData, req, res) => {
98
+ // const contentType = proxyRes.headers['content-type'] || '';
99
+ // if (contentType.includes('text/html')) {
100
+ // const $ = cheerio.load(proxyResData.toString('utf-8'));
101
+ // // Example DOM manipulation
102
+ // $('title').text('Modified Title');
103
+ // return $.html();
104
+ // }
105
+ // return proxyResData;
106
+ // },
107
+ // })
108
+ // );
109
+
110
+ // Middleware for static files
111
+ const staticPath = path . join ( componentPath , 'public' ) ;
112
+ if ( fs . existsSync ( staticPath ) ) {
113
+ app . use ( express . static ( staticPath ) ) ;
114
+ console . log ( `Serving static files from: ${ staticPath } ` ) ;
115
+ }
116
+
117
+ // Middleware for subPath handling
118
+ // app.use((req, res, next) => {
119
+ // if (config.subPath && !req.url.startsWith(`/${config.subPath}/`)) {
120
+ // return next(); // Not a matching path; skip handling
121
+ // }
122
+
123
+ // // Rewrite the URL to remove the subPath prefix
124
+ // req.url = config.subPath
125
+ // ? req.url.replace(new RegExp(`^/${config.subPath}/`), '/')
126
+ // : req.url;
127
+
128
+ // next();
129
+ // });
130
+
131
+ // Hook into `options.servers.http`
132
+ config . servers . http ( async ( request , nextHandler ) => {
133
+ const { _nodeRequest : req , _nodeResponse : res } = request ;
134
+
135
+ app . handle ( req , res , ( err ) => {
136
+ if ( err ) {
137
+ console . error ( `Error handling request: ${ err . message } ` ) ;
138
+ res . statusCode = 500 ;
139
+ res . end ( 'Internal Server Error' ) ;
140
+ } else {
141
+ nextHandler ( request ) ;
142
+ }
143
+ } ) ;
144
+ } ) ;
145
+
146
+ // Start the Express server
147
+ const port = config . port ;
148
+ app . listen ( port , ( ) => {
149
+ console . log ( `Express.js server is running on port ${ port } ` ) ;
150
+ } ) ;
151
+
152
+ return true ;
153
+ } ,
154
+ } ;
160
155
}
0 commit comments