@@ -14,7 +14,8 @@ const packageJSON = require('../package.json');
1414 * @property {boolean } [brotli] Defaults to false
1515 * @property {boolean } [embeddable] Defaults to false
1616 * @property {boolean } [stream] Defaults to false
17- * @property {string } [index] Defaults to none
17+ * @property {string } [directoryIndex] Defaults to none
18+ * @property {string } [defaultExtension] Defaults to n one
1819 * @property {string } [csp] Defaults to none
1920 */
2021
@@ -56,7 +57,8 @@ const FILE_SCHEMES = {
5657 supportFetch : true ,
5758 embeddable : true ,
5859 stream : true ,
59- index : '.html' ,
60+ directoryIndex : 'index.html' ,
61+ defaultExtension : '.html' ,
6062 csp : "default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; script-src 'self' 'unsafe-inline'"
6163 } ,
6264 'tw-update' : {
@@ -207,15 +209,19 @@ const createModernProtocolHandler = (metadata) => {
207209 } ;
208210
209211 try {
210- const parsedURL = new URL ( request . url ) ;
212+ let parsedURL = new URL ( request . url ) ;
213+ if ( parsedURL . pathname . endsWith ( '/' ) && metadata . directoryIndex ) {
214+ parsedURL = new URL ( metadata . directoryIndex , parsedURL ) ;
215+ }
216+
211217 let resolved = path . join ( root , parsedURL . pathname ) ;
212218 if ( ! resolved . startsWith ( root ) ) {
213219 return createErrorResponse ( new Error ( 'Path traversal blocked' ) ) ;
214220 }
215221
216222 let fileExtension = path . extname ( resolved ) ;
217- if ( ! fileExtension && metadata . index ) {
218- fileExtension = metadata . index ;
223+ if ( ! fileExtension && metadata . defaultExtension ) {
224+ fileExtension = metadata . defaultExtension ;
219225 resolved = `${ resolved } ${ fileExtension } ` ;
220226 }
221227
@@ -275,16 +281,20 @@ const createLegacyBrotliProtocolHandler = (metadata) => {
275281 } ;
276282
277283 try {
278- const parsedURL = new URL ( request . url ) ;
284+ let parsedURL = new URL ( request . url ) ;
285+ if ( parsedURL . pathname . endsWith ( '/' ) && metadata . directoryIndex ) {
286+ parsedURL = new URL ( metadata . directoryIndex , parsedURL ) ;
287+ }
288+
279289 let resolved = path . join ( root , parsedURL . pathname ) ;
280290 if ( ! resolved . startsWith ( root ) ) {
281291 returnErrorPage ( new Error ( 'Path traversal blocked' ) ) ;
282292 return ;
283293 }
284294
285295 let fileExtension = path . extname ( resolved ) ;
286- if ( ! fileExtension && metadata . index ) {
287- fileExtension = metadata . index ;
296+ if ( ! fileExtension && metadata . defaultExtension ) {
297+ fileExtension = metadata . defaultExtension ;
288298 resolved = `${ resolved } ${ fileExtension } ` ;
289299 }
290300
@@ -337,14 +347,23 @@ const createLegacyFileProtocolHandler = (metadata) => {
337347 } ;
338348
339349 try {
340- const parsedURL = new URL ( request . url ) ;
341- const resolved = path . join ( root , parsedURL . pathname ) ;
350+ let parsedURL = new URL ( request . url ) ;
351+ if ( parsedURL . pathname . endsWith ( '/' ) && metadata . directoryIndex ) {
352+ parsedURL = new URL ( metadata . directoryIndex , parsedURL ) ;
353+ }
354+
355+ let resolved = path . join ( root , parsedURL . pathname ) ;
342356 if ( ! resolved . startsWith ( root ) ) {
343357 returnErrorResponse ( new Error ( 'Path traversal blocked' ) , 'path-traversal' ) ;
344358 return ;
345359 }
346360
347- const fileExtension = path . extname ( resolved ) ;
361+ let fileExtension = path . extname ( resolved ) ;
362+ if ( ! fileExtension && metadata . defaultExtension ) {
363+ fileExtension = metadata . defaultExtension ;
364+ resolved = `${ resolved } ${ fileExtension } ` ;
365+ }
366+
348367 const mimeType = MIME_TYPES . get ( fileExtension ) ;
349368 if ( ! mimeType ) {
350369 returnErrorResponse ( new Error ( `Invalid file extension: ${ fileExtension } ` ) , 'invalid-extension' ) ;
0 commit comments