@@ -255,6 +255,63 @@ describe('Resolve trailing slash', () => {
255255 } )
256256 } )
257257
258+ describe ( 'appendTrailingSlash middleware with skip option' , ( ) => {
259+ const hasExtension = ( path : string ) : boolean => / \. \w + $ / . test ( path . split ( '/' ) . at ( - 1 ) ?? '' )
260+ const app = new Hono ( { strict : true } )
261+ app . use ( '*' , appendTrailingSlash ( { skip : hasExtension } ) )
262+
263+ app . get ( '/page/' , ( c ) => c . text ( 'ok' ) )
264+
265+ it ( 'should not redirect paths with file extensions' , async ( ) => {
266+ const resp = await app . request ( '/foo.html' )
267+
268+ expect ( resp . status ) . toBe ( 404 )
269+ } )
270+
271+ it ( 'should redirect paths without file extensions' , async ( ) => {
272+ const resp = await app . request ( '/page' )
273+
274+ expect ( resp . status ) . toBe ( 301 )
275+ const loc = new URL ( resp . headers . get ( 'location' ) ! )
276+ expect ( loc . pathname ) . toBe ( '/page/' )
277+ } )
278+ } )
279+
280+ describe ( 'appendTrailingSlash middleware with alwaysRedirect and skip options' , ( ) => {
281+ const hasExtension = ( path : string ) : boolean => / \. \w + $ / . test ( path . split ( '/' ) . at ( - 1 ) ?? '' )
282+ const app = new Hono ( )
283+ app . use ( '*' , appendTrailingSlash ( { alwaysRedirect : true , skip : hasExtension } ) )
284+
285+ app . get ( '/' , ( c ) => c . text ( 'ok' ) )
286+ app . get ( '/my-path/*' , ( c ) => c . text ( 'wildcard' ) )
287+
288+ it ( 'should redirect paths without extensions' , async ( ) => {
289+ const resp = await app . request ( '/my-path/something' )
290+ const loc = new URL ( resp . headers . get ( 'location' ) ! )
291+
292+ expect ( resp . status ) . toBe ( 301 )
293+ expect ( loc . pathname ) . toBe ( '/my-path/something/' )
294+ } )
295+
296+ it ( 'should not redirect paths with file extensions' , async ( ) => {
297+ const resp = await app . request ( '/my-path/style.css' )
298+
299+ expect ( resp . status ) . toBe ( 200 )
300+ } )
301+
302+ it ( 'should not redirect paths with extensions like .html' , async ( ) => {
303+ const resp = await app . request ( '/my-path/page.html' )
304+
305+ expect ( resp . status ) . toBe ( 200 )
306+ } )
307+
308+ it ( 'should handle HEAD request for paths with extensions' , async ( ) => {
309+ const resp = await app . request ( '/my-path/script.js' , { method : 'HEAD' } )
310+
311+ expect ( resp . status ) . toBe ( 200 )
312+ } )
313+ } )
314+
258315 describe ( 'appendTrailingSlash middleware with alwaysRedirect option' , ( ) => {
259316 const app = new Hono ( )
260317 app . use ( '*' , appendTrailingSlash ( { alwaysRedirect : true } ) )
0 commit comments