Skip to content

feat(serve-static): support absolute path #257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jul 19, 2025

Conversation

yusukebe
Copy link
Member

@yusukebe yusukebe commented Jul 14, 2025

Fixies #187
Related to #203 #238

This PR enables serve-static to support absolute paths, but both root and path options.

I considered that we should move the serve-static feature to the main honojs/hono core related to #203 honojs/hono#3483. However, if so, we need to update the peer dependencies for hono so that we can add this feature to this project separately from honojs/hono.

@@ -54,7 +54,7 @@
}
},
"scripts": {
"test": "node --expose-gc ./node_modules/.bin/jest",
"test": "node --expose-gc node_modules/jest/bin/jest.js",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support Windows on CI.

@yusukebe yusukebe marked this pull request as ready for review July 14, 2025 23:08
@yusukebe
Copy link
Member Author

Hi @usualoma

Can you review this, please?

Copy link
Member

@usualoma usualoma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @yusukebe

Thanks for creating the pull request.
I've added a comment, so please check it out.

@@ -68,7 +68,9 @@ describe('Serve Static Middleware', () => {
expect(res.status).toBe(200)
expect(res.text).toBe('<h1>Hello Hono</h1>')
expect(res.headers['content-type']).toBe('text/html; charset=utf-8')
expect(res.headers['x-custom']).toBe('Found the file at ./test/assets/static/index.html')
expect(res.headers['x-custom']).toMatch(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To simplify implementation, make the path passed to onFound an absolute path.

app.use(
  '/static/*',
  serveStatic({
    root: './test/assets',
    onFound: (path, c) => {
      // path is an absolute path
      c.header('X-Custom', `Found the file at ${path}`)
    },
  })
)

@yusukebe
Copy link
Member Author

@usualoma

Thank you for reviewing. I made it simple using Node.js API. What do you think of this?

path = addCurrentDirPrefix(path)
} else {
// Security check: prevent path traversal attacks
if (!optionPath && !path.startsWith(rootResolved)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

path.startsWith(rootResolved)

path = addCurrentDirPrefix(path)
if (optionPath) {
// Use path option directly if specified
path = resolve(optionPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the current main branch, I think "root" is also used here.

Suggested change
path = resolve(optionPath)
path = resolve(join(optionRoot, optionPath))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@usualoma Thanks.

I think join is not needed, so it should beresolve(optionRoot, optionPath).

I aslo added the tests and the change is here:

f6f5b90

What do you think of this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yusukebe Thank you!

The behavior when specifying an absolute path in path will change from before.

app.use('*', serveStatic({
    root: 'public',
    path: '/file.html',
}))

Previously, it behaved as if it joined to root. If this is an intentional change in behavior, I think it's OK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@usualoma

Thank you for pointing that out! It's better to keep the current behavior. I updated the code: d26e6ee

Please review it!

@yusukebe yusukebe force-pushed the feat/serve-static-absolute-path branch from 18ebc11 to 8f15053 Compare July 16, 2025 22:39
Copy link
Member

@usualoma usualoma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. LGTM!

@yusukebe
Copy link
Member Author

@usualoma Thank you for reviewing!

Landing it.

@yusukebe yusukebe merged commit a0be2f4 into main Jul 19, 2025
4 checks passed
@yusukebe yusukebe deleted the feat/serve-static-absolute-path branch July 19, 2025 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants