Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: tus/tus-node-server
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9ac6bf9e4964f86b93a36f765405ffc43f535c5e
Choose a base ref
...
head repository: tus/tus-node-server
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f6670b04f661562f880f52a7e3e00c503cbe3d19
Choose a head ref
Loading
Showing with 11,517 additions and 6,708 deletions.
  1. +0 −28 .eslintrc
  2. +26 −0 .eslintrc.js
  3. +11 −0 .github/dependabot.yaml
  4. +5 −0 .github/scripts/decrypt_secret.sh
  5. +44 −0 .github/workflows/ci.yml
  6. +6 −3 .gitignore
  7. +0 −11 .travis.yml
  8. +77 −27 README.md
  9. +0 −91 demo/index.html
  10. +0 −100 demo/index.js
  11. +27 −16 demo/server.js
  12. +166 −0 index.d.ts
  13. +2 −0 index.js
  14. BIN keyfile.json.enc
  15. BIN keyfile.json.gpg
  16. +39 −29 lib/Server.js
  17. +33 −0 lib/configstores/MemoryConfigstore.js
  18. +13 −1 lib/constants.js
  19. +13 −10 lib/handlers/BaseHandler.js
  20. +27 −0 lib/handlers/DeleteHandler.js
  21. +63 −0 lib/handlers/GetHandler.js
  22. +32 −41 lib/handlers/HeadHandler.js
  23. +3 −5 lib/handlers/OptionsHandler.js
  24. +47 −30 lib/handlers/PatchHandler.js
  25. +68 −16 lib/handlers/PostHandler.js
  26. +77 −0 lib/models/Metadata.js
  27. +131 −0 lib/models/StreamSplitter.js
  28. +1 −3 lib/models/Uid.js
  29. +37 −53 lib/stores/DataStore.js
  30. +87 −61 lib/stores/FileStore.js
  31. +102 −78 lib/stores/GCSDataStore.js
  32. +288 −254 lib/stores/S3Store.js
  33. +8 −1 lib/validators/RequestValidator.js
  34. +8,783 −5,177 package-lock.json
  35. +27 −21 package.json
  36. +16 −19 test/Test-BaseHandler.js
  37. +20 −19 test/Test-DataStore.js
  38. +55 −0 test/Test-DeleteHandler.js
  39. +126 −53 test/Test-EndToEnd.js
  40. +78 −199 test/Test-FileStore.js
  41. +27 −203 test/Test-GCSDataStore.js
  42. +191 −0 test/Test-GetHandler.js
  43. +60 −32 test/Test-HeadHandler.js
  44. +88 −0 test/Test-Metadata.js
  45. +1 −1 test/Test-OptionsHandler.js
  46. +70 −42 test/Test-PatchHandler.js
  47. +158 −23 test/Test-PostHandler.js
  48. +15 −0 test/Test-RequestValidator.js
  49. +34 −0 test/Test-S3DataStore.js
  50. +162 −60 test/Test-Server.js
  51. +163 −0 test/Test-Stores.shared.js
  52. +10 −1 test/Test-Uid.js
  53. BIN test/{ → fixtures}/test.mp4
28 changes: 0 additions & 28 deletions .eslintrc

This file was deleted.

26 changes: 26 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
extends: '@vimeo/eslint-config-player/es6',
env: {
node: true,
es6: true,
},
settings: {
ecmascript: 6,
esnext: true,
},
parser: 'babel-eslint',
globals: {
console: false,
},
rules: {
'camelcase': 0,
'comma-dangle': [1, 'always-multiline'],
'max-nested-callbacks': ['error', 4],
'max-params': ['error', 7],
'complexity': ['error', 14],
'prefer-rest-params': 0,
'prefer-spread': 0,
'strict': 0,
'no-warning-comments': 0,
},
};
11 changes: 11 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly

- package-ecosystem: npm
directory: /
schedule:
interval: monthly
5 changes: 5 additions & 0 deletions .github/scripts/decrypt_secret.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

# --batch to prevent interactive command --yes to assume "yes" for questions
gpg --quiet --batch --yes --decrypt --passphrase="$KEYFILE_PASSPHRASE" \
--output keyfile.json keyfile.json.gpg
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Node.js CI
on:
push:
branches: [ master ]
pull_request_target:
types: [ opened, synchronize, reopened ]
pull_request:
types: [ opened, synchronize, reopened ]
paths:
- .github/workflows/ci.yml

concurrency: ${{ github.workflow }}--${{ github.ref }}

jobs:
CI:
runs-on: ubuntu-latest
strategy:
# We do not want to run CRUD tests in parallel
max-parallel: 1
matrix:
node-version: [14.x, 16.x, 18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Decrypt keyfile
run: ./.github/scripts/decrypt_secret.sh
env:
KEYFILE_PASSPHRASE: ${{secrets.KEYFILE_PASSPHRASE}}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test
env:
AWS_BUCKET: ${{secrets.AWS_BUCKET}}
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_REGION: ${{secrets.AWS_REGION}}
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.idea

.env

# Logs
logs
*.log
@@ -29,13 +33,12 @@ node_modules

# Example local FileStore
example/files
files/
test/output

#OSX
.DS_Store

*.sublime-workspace

# Keyfile will be decrypted from keyfile.json.enc by travis
# https://docs.travis-ci.com/user/encrypting-files/
# Keyfile will be decrypted from keyfile.json.enc by GitHub Actions
keyfile.json
11 changes: 0 additions & 11 deletions .travis.yml

This file was deleted.

104 changes: 77 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# tus-node-server
[![npm version](https://badge.fury.io/js/tus-node-server.svg)](https://badge.fury.io/js/tus-node-server)
[![Build Status](https://travis-ci.org/tus/tus-node-server.svg?branch=master)](https://travis-ci.org/tus/tus-node-server)
[![Coverage Status](https://coveralls.io/repos/github/tus/tus-node-server/badge.svg?branch=master)](https://coveralls.io/github/tus/tus-node-server?branch=master)
[![Dependency Status](https://david-dm.org/tus/tus-node-server.svg)](https://david-dm.org/tus/tus-node-server#info=dependencies)
[![Build Status](https://github.com/tus/tus-node-server/actions/workflows/ci.yml/badge.svg)](https://github.com/tus/tus-node-server/actions/workflows/ci.yml)

tus is a new open protocol for resumable uploads built on HTTP. This is the [tus protocol 1.0.0](http://tus.io/protocols/resumable-upload.html) node.js server implementation.

@@ -17,15 +15,14 @@ $ npm install tus-node-server
- **Local File Storage**
```js
server.datastore = new tus.FileStore({
path: '/files'
directory: './files'
});
```

- **Google Cloud Storage**
```js
server.datastore = new tus.GCSDataStore({
path: '/files',
projectId: 'project-id',
keyFilename: 'path/to/your/keyfile.json',
bucket: 'bucket-name',
@@ -36,13 +33,11 @@ $ npm install tus-node-server
```js
server.datastore = new tus.S3Store({
path: '/files',
bucket: 'bucket-name',
accessKeyId: 'access-key-id',
secretAccessKey: 'secret-access-key',
region: 'eu-west-1',
partSize: 8 * 1024 * 1024, // each uploaded part will have ~8MB,
tmpDirPrefix: 'tus-s3-store',
});
```

@@ -58,10 +53,8 @@ $ docker run -p 1080:8080 -d bhstahl/tus-node-deploy
```js
const tus = require('tus-node-server');
const server = new tus.Server();
server.datastore = new tus.FileStore({
path: '/files'
});
const server = new tus.Server({ path: '/files' });
server.datastore = new tus.FileStore({ directory: './files' });
const host = '127.0.0.1';
const port = 1080;
@@ -74,11 +67,10 @@ server.listen({ host, port }, () => {

```js
const tus = require('tus-node-server');
const server = new tus.Server();
server.datastore = new tus.FileStore({
path: '/files'
});
const server = new tus.Server({ path: '/files' });
server.datastore = new tus.FileStore({ directory: './files' });

const express = require('express');
const app = express();
const uploadApp = express();
uploadApp.all('*', server.handle.bind(server));
@@ -96,15 +88,14 @@ const http = require('http');
const url = require('url');
const Koa = require('koa')
const tus = require('tus-node-server');
const tusServer = new tus.Server();

const tusServer = new tus.Server({ path: '/files' });
tusServer.datastore = new tus.FileStore({ directory: './files' });

const app = new Koa();
const appCallback = app.callback();
const port = 1080;

tusServer.datastore = new tus.FileStore({
path: '/files',
});

const server = http.createServer((req, res) => {
const urlPath = url.parse(req.url).pathname;
@@ -120,16 +111,57 @@ const server = http.createServer((req, res) => {
server.listen(port)
```

#### Use tus-node-server with [Fastify](https://www.fastify.io)

```js
const tus = require('tus-node-server');
const tusServer = new tus.Server({ path: '/files' });
tusServer.datastore = new tus.FileStore({ directory: './files' });

const fastify = require('fastify')({ logger: true });

/**
* add new content-type to fastify forewards request
* without any parser to leave body untouched
* @see https://www.fastify.io/docs/latest/Reference/ContentTypeParser/
*/
fastify.addContentTypeParser(
'application/offset+octet-stream', async () => true
);

/**
* let tus handle preparation and filehandling requests
* fastify exposes raw nodejs http req/res via .raw property
* @see https://www.fastify.io/docs/latest/Reference/Request/
* @see https://www.fastify.io/docs/latest/Reference/Reply/#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);
}
});
```

## Features
#### Events:

Execute code when lifecycle events happen by adding event handlers to your server.

```js
const Server = require('tus-node-server').Server;
const tus = require('tus-node-server');
const EVENTS = require('tus-node-server').EVENTS;

const server = new Server();
const server = new tus.Server({ path: '/files' });
server.datastore = new tus.FileStore({ directory: './files' });

server.on(EVENTS.EVENT_UPLOAD_COMPLETE, (event) => {
console.log(`Upload complete for file ${event.file.id}`);
});
@@ -170,27 +202,45 @@ server.on(EVENTS.EVENT_UPLOAD_COMPLETE, (event) => {
}
```
- `EVENT_FILE_DELETED`: Fired when a `DELETE` request finishes deleting the file
_Example payload:_
```
{
file_id: '7b26bf4d22cf7198d3b3706bf0379794'
}
```
#### Custom `GET` handlers:
Add custom `GET` handlers to suit your needs, similar to [Express routing](https://expressjs.com/en/guide/routing.html).
```js
const server = new Server();
const server = new tus.Server({ path: '/files' });
server.datastore = new tus.FileStore({ directory: './files' });
server.get('/uploads', (req, res) => {
// Read from your DataStore
fs.readdir(server.datastore.path, (err, files) => {
fs.readdir(server.datastore.directory, (err, files) => {
// Format the JSON response and send it
}
});
```

#### Custom file names:

The default naming of files is a random crypto hex string. When using your own `namingFunction`, make sure to create URL friendly names such as removing spaces.
```js
const fileNameFromUrl = (req) => {
return req.url.replace(/\//g, '-');
const crypto = require('crypto');

// req is http.IncomingMessage
const randomString = (req) => {
// same as the default implementation
return crypto.randomBytes(16).toString('hex');
}

server.datastore = new tus.FileStore({
const server = new tus.Server({
path: '/files',
namingFunction: fileNameFromUrl
namingFunction: randomString,
});
```

Loading