Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-ducks-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tus/server": minor
---

Use srvx for convert Node.js req/res to Request/Response. This also comes with a performance boost. When using `server.handle()` in a Node.js environment, you can now access the orignal req/res via `req.node.req`/`req.node.res`.
53 changes: 36 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"workspaces": [
"packages/*",
"test"
Expand Down
3 changes: 3 additions & 0 deletions packages/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ observability.
The main server request handler invoked on every request.
Use this to integrate into your existing Node.js server.

This handler converts `http.IncomingMessage`/`http.ServerResponse` to `Request`/`Response`.
You can still access the Node.js versions via `req.node.req`/`req.node.res` in the hooks.

#### `server.handleWeb(req: Request)`

The main server request handler invoked on every request.
Expand Down
5 changes: 3 additions & 2 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
"@tus/utils": "^0.6.0",
"debug": "^4.3.4",
"lodash.throttle": "^4.1.1",
"set-cookie-parser": "^2.7.1"
"set-cookie-parser": "^2.7.1",
"srvx": "^0.2.7"
},
"devDependencies": {
"@types/debug": "^4.1.12",
"@types/lodash.throttle": "^4.1.9",
"@types/mocha": "^10.0.6",
"@types/set-cookie-parser": "^2.4.10",
"@types/node": "^22.13.7",
"@types/set-cookie-parser": "^2.4.10",
"@types/sinon": "^17.0.3",
"@types/supertest": "^2.0.16",
"mocha": "^11.0.1",
Expand Down
30 changes: 17 additions & 13 deletions packages/server/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import http from 'node:http'
import {EventEmitter} from 'node:events'

import {toNodeHandler} from 'srvx/node'
import debug from 'debug'
import {EVENTS, ERRORS, EXPOSED_HEADERS, REQUEST_METHODS, TUS_RESUMABLE} from '@tus/utils'
import type {DataStore, Upload, CancellationContext} from '@tus/utils'

import {BaseHandler} from './handlers/BaseHandler.js'
import {GetHandler} from './handlers/GetHandler.js'
import {HeadHandler} from './handlers/HeadHandler.js'
import {OptionsHandler} from './handlers/OptionsHandler.js'
Expand All @@ -15,7 +15,6 @@ import {DeleteHandler} from './handlers/DeleteHandler.js'
import {validateHeader} from './validators/HeaderValidator.js'
import type {ServerOptions, RouteHandler, WithOptional} from './types.js'
import {MemoryLocker} from './lockers/index.js'
import {getRequest, setResponse} from './web.js'

type Handlers = {
GET: InstanceType<typeof GetHandler>
Expand Down Expand Up @@ -119,19 +118,11 @@ export class Server extends EventEmitter {
}

get(path: string, handler: RouteHandler) {
this.handlers.GET.registerPath(this.options.path + path, handler)
this.handlers.GET.registerPath(path, handler)
}

async handle(req: http.IncomingMessage, res: http.ServerResponse) {
const {proto, host} = BaseHandler.extractHostAndProto(
// @ts-expect-error it's fine
new Headers(req.headers),
this.options.respectForwardedHeaders
)
const base = `${proto}://${host}${this.options.path}`
const webReq = await getRequest({request: req, base})
const webRes = await this.handler(webReq)
return setResponse(res, webRes)
return toNodeHandler(this.handler.bind(this))(req, res)
}

async handleWeb(req: Request) {
Expand All @@ -142,6 +133,19 @@ export class Server extends EventEmitter {
const context = this.createContext()
const headers = new Headers()

// @ts-expect-error temporary until https://github.com/unjs/srvx/issues/44 is fixed
req.headers.get = (key: string) => {
for (const [k, v] of req.headers.entries()) {
if (k === key) {
if (v === '') {
return null
}
return v
}
}
return null
}

const onError = async (error: {
status_code?: number
body?: string
Expand All @@ -164,7 +168,7 @@ export class Server extends EventEmitter {
if (req.method === 'GET') {
const handler = this.handlers.GET
const res = await handler.send(req, context, headers).catch(onError)
context.abort
context.abort()
return res
}

Expand Down
Loading