Skip to content

Commit 3435875

Browse files
authored
fix(serve-static): fix onFound timing (#286)
1 parent 840c22b commit 3435875

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

src/serve-static.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ export const serveStatic = <E extends Env = any>(
105105
await options.onNotFound?.(path, c)
106106
return next()
107107
}
108-
await options.onFound?.(path, c)
109108

110109
const mimeType = getMimeType(path)
111110
c.header('Content-Type', mimeType || 'application/octet-stream')
@@ -133,37 +132,38 @@ export const serveStatic = <E extends Env = any>(
133132
}
134133
}
135134

135+
let result
136136
const size = stats.size
137+
const range = c.req.header('range') || ''
137138

138139
if (c.req.method == 'HEAD' || c.req.method == 'OPTIONS') {
139140
c.header('Content-Length', size.toString())
140141
c.status(200)
141-
return c.body(null)
142-
}
143-
144-
const range = c.req.header('range') || ''
145-
146-
if (!range) {
142+
result = c.body(null)
143+
} else if (!range) {
147144
c.header('Content-Length', size.toString())
148-
return c.body(createStreamBody(createReadStream(path)), 200)
149-
}
150-
151-
c.header('Accept-Ranges', 'bytes')
152-
c.header('Date', stats.birthtime.toUTCString())
145+
result = c.body(createStreamBody(createReadStream(path)), 200)
146+
} else {
147+
c.header('Accept-Ranges', 'bytes')
148+
c.header('Date', stats.birthtime.toUTCString())
149+
150+
const parts = range.replace(/bytes=/, '').split('-', 2)
151+
const start = parseInt(parts[0], 10) || 0
152+
let end = parseInt(parts[1], 10) || size - 1
153+
if (size < end - start + 1) {
154+
end = size - 1
155+
}
153156

154-
const parts = range.replace(/bytes=/, '').split('-', 2)
155-
const start = parseInt(parts[0], 10) || 0
156-
let end = parseInt(parts[1], 10) || size - 1
157-
if (size < end - start + 1) {
158-
end = size - 1
159-
}
157+
const chunksize = end - start + 1
158+
const stream = createReadStream(path, { start, end })
160159

161-
const chunksize = end - start + 1
162-
const stream = createReadStream(path, { start, end })
160+
c.header('Content-Length', chunksize.toString())
161+
c.header('Content-Range', `bytes ${start}-${end}/${stats.size}`)
163162

164-
c.header('Content-Length', chunksize.toString())
165-
c.header('Content-Range', `bytes ${start}-${end}/${stats.size}`)
163+
result = c.body(createStreamBody(stream), 206)
164+
}
166165

167-
return c.body(createStreamBody(stream), 206)
166+
await options.onFound?.(path, c)
167+
return result
168168
}
169169
}

test/serve-static.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ describe('Serve Static Middleware', () => {
1818
root: './test/assets',
1919
onFound: (path, c) => {
2020
c.header('X-Custom', `Found the file at ${path}`)
21+
if (c.req.query('type')) {
22+
c.header('Content-Type', c.req.query('type'))
23+
}
2124
},
2225
})
2326
)
@@ -182,6 +185,14 @@ describe('Serve Static Middleware', () => {
182185
)
183186
})
184187

188+
it('Should handle the `onFound` option', async () => {
189+
const res = await request(server).get(
190+
'/static/data.json?type=application/json;%20charset=utf-8'
191+
)
192+
expect(res.status).toBe(200)
193+
expect(res.headers['content-type']).toBe('application/json; charset=utf-8')
194+
})
195+
185196
it('Should handle double dots in URL', async () => {
186197
const res = await request(server).get('/static/../secret.txt')
187198
expect(res.status).toBe(404)

0 commit comments

Comments
 (0)