Skip to content

Commit ea2bf07

Browse files
authored
@tus/server: add lastPath arg to getFileIdFromRequest (#626)
* @tus/server: add `lastPath` arg to `getFileIdFromRequest` * Changeset
1 parent 117e1b2 commit ea2bf07

File tree

5 files changed

+28
-24
lines changed

5 files changed

+28
-24
lines changed

.changeset/smooth-kiwis-grow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tus/server': minor
3+
---
4+
5+
Add `lastPath` argument to `getFileIdFromRequest` to simplify a common use case.

packages/server/README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,11 @@ Checkout the example how to
106106

107107
#### `options.getFileIdFromRequest`
108108

109-
Control how the Upload-ID is extracted from the request (`(req) => string | void`) By
110-
default, it expects everything in the path after the last `/` to be the upload id.
109+
Control how the Upload-ID is extracted from the request
110+
(`(req, lastPath) => string | void`)
111+
112+
By default, it expects everything in the path after the last `/` to be the upload id.
113+
`lastPath` is everything after the last `/`.
111114

112115
Checkout the example how to
113116
[store files in custom nested directories](#example-store-files-in-custom-nested-directories).
@@ -157,7 +160,8 @@ This can be used to implement validation of upload metadata or add headers.
157160
#### `options.onUploadFinish`
158161

159162
`onUploadFinish` will be invoked after an upload is completed but before a response is
160-
returned to the client (`(req, res, upload) => Promise<{ res: http.ServerResponse, status_code?: number, headers?: Record<string, string | number>, body?: string }>`).
163+
returned to the client
164+
(`(req, res, upload) => Promise<{ res: http.ServerResponse, status_code?: number, headers?: Record<string, string | number>, body?: string }>`).
161165

162166
- You can optionally return `status_code`, `headers` and `body` to modify the response.
163167
Note that the tus specification does not allow sending response body nor status code
@@ -254,8 +258,9 @@ Called every [`postReceiveInterval`](#optionspostreceiveinterval) milliseconds f
254258
upload while it‘s being written to the store.
255259
256260
This means you are not guaranteed to get (all) events for an upload. For instance if
257-
`postReceiveInterval` is set to 1000ms and an PATCH request takes 500ms, no event is emitted.
258-
If the PATCH request takes 2500ms, you would get the offset at 2000ms, but not at 2500ms.
261+
`postReceiveInterval` is set to 1000ms and an PATCH request takes 500ms, no event is
262+
emitted. If the PATCH request takes 2500ms, you would get the offset at 2000ms, but not at
263+
2500ms.
259264
260265
Use `POST_FINISH` if you need to know when an upload is done.
261266
@@ -543,18 +548,13 @@ const server = new Server({
543548
id = Buffer.from(id, 'utf-8').toString('base64url')
544549
return `${proto}://${host}${path}/${id}`
545550
},
546-
getFileIdFromRequest(req) {
547-
const reExtractFileID = /([^/]+)\/?$/
548-
const match = reExtractFileID.exec(req.url as string)
549-
550-
if (!match || path.includes(match[1])) {
551-
return
552-
}
553-
554-
return Buffer.from(match[1], 'base64url').toString('utf-8')
551+
getFileIdFromRequest(req, lastPath) {
552+
// lastPath is everything after the last `/`
553+
// If your custom URL is different, this might be undefined
554+
// and you need to extract the ID yourself
555+
return Buffer.from(lastPath, 'base64url').toString('utf-8')
555556
},
556557
})
557-
558558
```
559559
560560
### Example: use with Nginx

packages/server/src/handlers/BaseHandler.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ export class BaseHandler extends EventEmitter {
6363
}
6464

6565
getFileIdFromRequest(req: http.IncomingMessage) {
66+
const match = reExtractFileID.exec(req.url as string)
67+
6668
if (this.options.getFileIdFromRequest) {
67-
return this.options.getFileIdFromRequest(req)
69+
const lastPath = match ? decodeURIComponent(match[1]) : undefined
70+
return this.options.getFileIdFromRequest(req, lastPath)
6871
}
69-
const match = reExtractFileID.exec(req.url as string)
7072

7173
if (!match || this.options.path.includes(match[1])) {
7274
return

packages/server/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export type ServerOptions = {
5353
* Control how the Upload-ID is extracted from the request.
5454
* @param req - The incoming HTTP request.
5555
*/
56-
getFileIdFromRequest?: (req: http.IncomingMessage) => string | void
56+
getFileIdFromRequest?: (req: http.IncomingMessage, lastPath?: string) => string | void
5757

5858
/**
5959
* Control how you want to name files.

packages/server/test/Server.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,12 @@ describe('Server', () => {
295295
id = Buffer.from(id, 'utf-8').toString('base64url')
296296
return `${proto}://${host}${path}/${id}`
297297
},
298-
getFileIdFromRequest(req) {
299-
const reExtractFileID = /([^/]+)\/?$/
300-
const match = reExtractFileID.exec(req.url as string)
301-
302-
if (!match || route.includes(match[1])) {
298+
getFileIdFromRequest(req, lastPath) {
299+
if (!lastPath) {
303300
return
304301
}
305302

306-
return Buffer.from(match[1], 'base64url').toString('utf-8')
303+
return Buffer.from(lastPath, 'base64url').toString('utf-8')
307304
},
308305
})
309306
const length = Buffer.byteLength('test', 'utf8').toString()

0 commit comments

Comments
 (0)