Socket
Socket
Sign inDemoInstall

@tus/server

Package Overview
Dependencies
Maintainers
3
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tus/server - npm Package Compare versions

Comparing version 1.0.0-beta.7 to 1.0.0

1

dist/server.d.ts

@@ -50,2 +50,3 @@ /// <reference types="node" />

handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<http.ServerResponse | stream.Writable | void>;
write(res: http.ServerResponse, status: number, body?: string, headers?: {}): http.ServerResponse<http.IncomingMessage>;
listen(...args: any[]): http.Server;

@@ -52,0 +53,0 @@ cleanUpExpiredUploads(): Promise<number>;

44

dist/server.js

@@ -82,10 +82,16 @@ "use strict";

}
const onError = (error) => {
const status_code = error.status_code || constants_1.ERRORS.UNKNOWN_ERROR.status_code;
const body = error.body || `${constants_1.ERRORS.UNKNOWN_ERROR.body}${error.message || ''}\n`;
return this.write(res, status_code, body);
};
try {
await this.options.onIncomingRequest?.(req, res);
}
catch (err) {
return onError(err);
}
if (req.method === 'GET') {
const handler = this.handlers.GET;
return handler.send(req, res).catch((error) => {
log(`[${handler.constructor.name}]`, error);
const status_code = error.status_code || constants_1.ERRORS.UNKNOWN_ERROR.status_code;
const body = error.body || `${constants_1.ERRORS.UNKNOWN_ERROR.body}${error.message || ''}\n`;
return handler.write(res, status_code, {}, body);
});
return handler.send(req, res).catch(onError);
}

@@ -97,4 +103,3 @@ // The Tus-Resumable header MUST be included in every request and

if (req.method !== 'OPTIONS' && req.headers['tus-resumable'] === undefined) {
res.writeHead(412, 'Precondition Failed');
return res.end('Tus-Resumable Required\n');
return this.write(res, 412, 'Tus-Resumable Required\n');
}

@@ -121,5 +126,3 @@ // Validate all required headers to adhere to the tus protocol

if (invalid_headers.length > 0) {
// The request was not configured to the tus protocol
res.writeHead(400, 'Bad Request');
return res.end(`Invalid ${invalid_headers.join(' ')}\n`);
return this.write(res, 400, `Invalid ${invalid_headers.join(' ')}\n`);
}

@@ -134,12 +137,13 @@ // Enable CORS

if (handler) {
return handler.send(req, res).catch((error) => {
log(`[${handler.constructor.name}]`, error);
const status_code = error.status_code || constants_1.ERRORS.UNKNOWN_ERROR.status_code;
const body = error.body || `${constants_1.ERRORS.UNKNOWN_ERROR.body}${error.message || ''}\n`;
return handler.write(res, status_code, {}, body);
});
return handler.send(req, res).catch(onError);
}
// 404 Anything else
res.writeHead(404, {});
res.write('Not found\n');
return this.write(res, 404, 'Not found\n');
}
write(res, status, body = '', headers = {}) {
if (status !== 204) {
// @ts-expect-error not explicitly typed but possible
headers['Content-Length'] = Buffer.byteLength(body, 'utf8');
}
res.writeHead(status, headers);
res.write(body);
return res.end();

@@ -146,0 +150,0 @@ }

@@ -11,3 +11,4 @@ /// <reference types="node" />

onUploadFinish?: (req: http.IncomingMessage, res: http.ServerResponse, upload: Upload) => Promise<http.ServerResponse>;
onIncomingRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
};
export type RouteHandler = (req: http.IncomingMessage, res: http.ServerResponse) => void;
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@tus/server",
"version": "1.0.0-beta.7",
"version": "1.0.0",
"description": "Tus resumable upload protocol in Node.js",

@@ -24,20 +24,20 @@ "main": "dist/index.js",

"dependencies": {
"debug": "^4.3.3"
"debug": "^4.3.4"
},
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/debug": "^4.1.8",
"@types/mocha": "^10.0.1",
"@types/node": "latest",
"@types/sinon": "^10.0.13",
"@types/node": "^20.5.7",
"@types/sinon": "^10.0.16",
"@types/supertest": "^2.0.12",
"eslint": "^8.29.0",
"eslint": "^8.48.0",
"eslint-config-custom": "0.0.0",
"mocha": "^10.1.0",
"node-mocks-http": "^1.12.1",
"mocha": "^10.2.0",
"node-mocks-http": "^1.13.0",
"should": "^13.2.3",
"sinon": "^15.0.4",
"supertest": "^6.3.2",
"sinon": "^15.2.0",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"tsconfig": "*",
"typescript": "latest"
"typescript": "^5.2.2"
},

@@ -44,0 +44,0 @@ "engines": {

@@ -5,3 +5,3 @@ # `@tus/server`

> The old package, `tus-node-server`, is considered unstable and will only receive security fixes.
> Make sure to use the new package, currently in beta at `1.0.0-beta.7`.
> Make sure to use the new package.

@@ -39,12 +39,12 @@ ## Contents

```js
const { Server } = require("@tus/server");
const { FileStore } = require("@tus/file-store");
const host = "127.0.0.1";
const port = 1080;
const {Server} = require('@tus/server')
const {FileStore} = require('@tus/file-store')
const host = '127.0.0.1'
const port = 1080
const server = new Server({
path: "/files",
datastore: new FileStore({ directory: "./files" }),
});
server.listen({ host, port });
path: '/files',
datastore: new FileStore({directory: './files'}),
})
server.listen({host, port})
```

@@ -85,3 +85,3 @@

If the function returns the (modified) response, the upload will be created.
If an error is thrown, the HTTP request will be aborted and the provided `body` and `status_code` (or their fallbacks) will be sent to the client.
You can `throw` an Object and the HTTP request will be aborted with the provided `body` and `status_code` (or their fallbacks).

@@ -95,6 +95,13 @@ This can be used to implement validation of upload metadata or add headers.

If the function returns the (modified) response, the upload will finish.
If an error is thrown, the HTTP request will be aborted and the provided `body` and `status_code` (or their fallbacks) will be sent to the client.
You can `throw` an Object and the HTTP request will be aborted with the provided `body` and `status_code` (or their fallbacks).
This can be used to implement post-processing validation.
#### `options.onIncomingRequest`
`onIncomingRequest` is a middleware function invoked before all handlers (`(req, res) => Promise<void>`)
This can be used for things like access control.
You can `throw` an Object and the HTTP request will be aborted with the provided `body` and `status_code` (or their fallbacks).
#### `server.handle(req, res)`

@@ -184,17 +191,17 @@

```js
const { Server } = require("@tus/server");
const { FileStore } = require("@tus/file-store");
const express = require("express");
const {Server} = require('@tus/server')
const {FileStore} = require('@tus/file-store')
const express = require('express')
const host = "127.0.0.1";
const port = 1080;
const app = express();
const uploadApp = express();
const host = '127.0.0.1'
const port = 1080
const app = express()
const uploadApp = express()
const server = new Server({
datastore: new FileStore({ directory: "/files" }),
});
datastore: new FileStore({directory: '/files'}),
})
uploadApp.all("*", server.handle.bind(server));
app.use("/uploads", uploadApp);
app.listen(port, host);
uploadApp.all('*', server.handle.bind(server))
app.use('/uploads', uploadApp)
app.listen(port, host)
```

@@ -205,28 +212,28 @@

```js
const http = require("node:http");
const url = require("node:url");
const Koa = require("koa");
const { Server } = require("@tus/server");
const { FileStore } = require("@tus/file-store");
const http = require('node:http')
const url = require('node:url')
const Koa = require('koa')
const {Server} = require('@tus/server')
const {FileStore} = require('@tus/file-store')
const app = new Koa();
const appCallback = app.callback();
const port = 1080;
const app = new Koa()
const appCallback = app.callback()
const port = 1080
const tusServer = new Server({
path: "/files",
datastore: new FileStore({ directory: "/files" }),
});
path: '/files',
datastore: new FileStore({directory: '/files'}),
})
const server = http.createServer((req, res) => {
const urlPath = url.parse(req.url).pathname;
const urlPath = url.parse(req.url).pathname
// handle any requests with the `/files/*` pattern
if (/^\/files\/.+/.test(urlPath.toLowerCase())) {
return tusServer.handle(req, res);
return tusServer.handle(req, res)
}
appCallback(req, res);
});
appCallback(req, res)
})
server.listen(port);
server.listen(port)
```

@@ -237,10 +244,10 @@

```js
const fastify = require("fastify")({ logger: true });
const { Server } = require("@tus/server");
const { FileStore } = require("@tus/file-store");
const fastify = require('fastify')({logger: true})
const {Server} = require('@tus/server')
const {FileStore} = require('@tus/file-store')
const tusServer = new Server({
path: "/files",
datastore: new FileStore({ directory: "./files" }),
});
path: '/files',
datastore: new FileStore({directory: './files'}),
})

@@ -253,5 +260,5 @@ /**

fastify.addContentTypeParser(
"application/offset+octet-stream",
'application/offset+octet-stream',
(request, payload, done) => done(null)
);
)

@@ -264,14 +271,14 @@ /**

*/
fastify.all("/files", (req, res) => {
tusServer.handle(req.raw, res.raw);
});
fastify.all("/files/*", (req, res) => {
tusServer.handle(req.raw, res.raw);
});
fastify.all('/files', (req, res) => {
tusServer.handle(req.raw, res.raw)
})
fastify.all('/files/*', (req, res) => {
tusServer.handle(req.raw, res.raw)
})
fastify.listen(3000, (err) => {
if (err) {
fastify.log.error(err);
process.exit(1);
fastify.log.error(err)
process.exit(1)
}
});
})
```

@@ -286,5 +293,5 @@

```ts
import type { NextApiRequest, NextApiResponse } from "next";
import { Server, Upload } from "@tus/server";
import { FileStore } from "@tus/file-store";
import type {NextApiRequest, NextApiResponse} from 'next'
import {Server, Upload} from '@tus/server'
import {FileStore} from '@tus/file-store'

@@ -299,3 +306,3 @@ /**

},
};
}

@@ -305,8 +312,8 @@ const tusServer = new Server({

// ie /api/upload
path: "/api/upload",
datastore: new FileStore({ directory: "./files" }),
});
path: '/api/upload',
datastore: new FileStore({directory: './files'}),
})
export default function handler(req: NextApiRequest, res: NextApiResponse) {
return tusServer.handle(req, res);
return tusServer.handle(req, res)
}

@@ -318,3 +325,3 @@ ```

```js
const { Server } = require("@tus/server");
const {Server} = require('@tus/server')
// ...

@@ -325,13 +332,44 @@

async onUploadCreate(req, res, upload) {
const { ok, expected, received } = validateMetadata(upload);
const {ok, expected, received} = validateMetadata(upload)
if (!ok) {
const body = `Expected "${expected}" in "Upload-Metadata" but received "${received}"`;
throw { status_code: 500, body }; // if undefined, falls back to 500 with "Internal server error".
const body = `Expected "${expected}" in "Upload-Metadata" but received "${received}"`
throw {status_code: 500, body} // if undefined, falls back to 500 with "Internal server error".
}
// We have to return the (modified) response.
return res;
return res
},
})
```
### Example: access control
Access control is opinionated and can be done in different ways.
This example is psuedo-code for what it could look like with JSON Web Tokens.
```js
const { Server } = require("@tus/server");
// ...
const server = new Server({
// ..
async onIncomingRequest(req, res) {
const token = req.headers.authorization;
if (!token) {
throw { status_code: 401, body: 'Unauthorized' })
}
try {
const decodedToken = await jwt.verify(token, 'your_secret_key')
req.user = decodedToken
} catch (error) {
throw { status_code: 401, body: 'Invalid token' })
}
if (req.user.role !== 'admin') {
throw { status_code: 403, body: 'Access denied' })
}
},
});
server.listen({ host, port });
```

@@ -338,0 +376,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc