Skip to content

Commit

Permalink
Merge branch 'master' into 1.x
Browse files Browse the repository at this point in the history
* master:
  0.9.0
  Allow `credentials` instead of key/secret for the S3 store (#282)
  Clarify example for Fastify (#311)
  • Loading branch information
Murderlon committed Nov 18, 2022
2 parents 981e992 + 1e3735b commit 24de83b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 15 deletions.
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ $ npm install tus-node-server

- **Amazon S3**

using Key/Secret
```js
server.datastore = new tus.S3Store({
bucket: 'bucket-name',
Expand All @@ -43,6 +44,23 @@ $ npm install tus-node-server
})
```

using [credentials](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Credentials.html#constructor-property) to fetch credentials inside a AWS container, such as an ECS container, which will inject the required environment variables. The `credentials` config is directly passed into the AWS SDK so you can refer to the AWS docs for the supported values for `credentials`.

For example, with `ECSCredentials`:

```js
server.datastore = new tus.S3Store({
path: '/files',
bucket: 'bucket-name',
credentials: new AWS.ECSCredentials({
httpOptions: { timeout: 5000 },
maxRetries: 10,
}),
region: 'eu-west-1',
partSize: 8 * 1024 * 1024, // each uploaded part will have ~8MB,
tmpDirPrefix: 'tus-s3-store',
});
```
## Quick Start

#### Use the [tus-node-deploy](https://hub.docker.com/r/bhstahl/tus-node-deploy/) Docker image
Expand Down Expand Up @@ -129,7 +147,9 @@ const fastify = require('fastify')({logger: true})
* without any parser to leave body untouched
* @see https://www.fastify.io/docs/latest/Reference/ContentTypeParser/
*/
fastify.addContentTypeParser('application/offset+octet-stream', async () => true)
fastify.addContentTypeParser(
'application/offset+octet-stream', (request, payload, done) => done(null)
);

/**
* let tus handle preparation and filehandling requests
Expand Down Expand Up @@ -254,7 +274,7 @@ const server = new tus.Server({
})
```
## Demo
## Demo
Start the demo server using Local File Storage
Expand Down
31 changes: 19 additions & 12 deletions lib/stores/S3Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ function calculateOffsetFromParts(parts?: aws.S3.Parts) {
return parts && parts.length > 0 ? parts.reduce((a, b) => a + b.Size, 0) : 0
}

type Options = {
accessKeyId: string
secretAccessKey: string
type Base = {
bucket: string
region?: string
partSize?: number
}

type Options =
| ({accessKeyId: string; secretAccessKey: string; credentials?: never} & Base)
| ({
credentials: aws.RemoteCredentials
accessKeyId?: never
secretAccessKey?: never
} & Base)

type MetadataValue = {file: Upload; upload_id: string}
// Implementation (based on https://github.com/tus/tusd/blob/master/s3store/s3store.go)
//
Expand Down Expand Up @@ -70,9 +76,12 @@ export default class S3Store extends DataStore {

constructor(options: Options) {
super()
assert.ok(options.accessKeyId, '[S3Store] `accessKeyId` must be set')
assert.ok(options.secretAccessKey, '[S3Store] `secretAccessKey` must be set')
assert.ok(options.bucket, '[S3Store] `bucket` must be set')
if (options.accessKeyId || options.secretAccessKey) {
assert.ok(options.accessKeyId, '[S3Store] `accessKeyId` must be set')
assert.ok(options.secretAccessKey, '[S3Store] `secretAccessKey` must be set')
} else {
assert.ok(options.credentials, '[S3Store] `credentials` must be set')
}

this.extensions = ['creation', 'creation-with-upload', 'creation-defer-length']
this.bucket_name = options.bucket
Expand Down Expand Up @@ -441,13 +450,12 @@ export default class S3Store extends DataStore {

try {
const parts = await this.retrieveParts(id)
return {
return new Upload({
id,
...this.cache.get(id)?.file,
offset: calculateOffsetFromParts(parts),
size: metadata.file.size,
sizeIsDeferred: metadata.file.sizeIsDeferred,
}
})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.code !== 'NoSuchUpload') {
Expand All @@ -458,13 +466,12 @@ export default class S3Store extends DataStore {
// When the last part of an upload is finished and the file is successfully written to S3,
// the upload will no longer be present and requesting it will result in a 404.
// In that case we return the upload_length as size.
return {
return new Upload({
id,
...this.cache.get(id)?.file,
offset: metadata.file.offset,
size: metadata.file.size,
sizeIsDeferred: metadata.file.sizeIsDeferred,
}
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "tus-node-server",
"version": "0.8.1",
"version": "0.9.0",
"description": "Node.js tus server",
"packageManager": "yarn@3.2.3",
"keywords": [
Expand Down

0 comments on commit 24de83b

Please sign in to comment.