Skip to content

Commit

Permalink
Merge branch 'main' of github.com:tus/tus-js-client into ietf-draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Acconut committed Aug 18, 2023
2 parents a6ad586 + ea830d5 commit e1f9cc7
Show file tree
Hide file tree
Showing 11 changed files with 368 additions and 195 deletions.
14 changes: 7 additions & 7 deletions demos/reactnative/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5149,19 +5149,19 @@ schedule@^0.3.0:
object-assign "^4.1.1"

"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.5.0, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==

[email protected]:
version "7.0.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==

semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==

[email protected]:
version "0.17.1"
Expand Down Expand Up @@ -5582,7 +5582,7 @@ trim-right@^1.0.1:
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=

"tus-js-client@file:../..":
version "3.0.1"
version "3.1.1"
dependencies:
buffer-from "^1.1.2"
combine-errors "^3.0.3"
Expand Down
3 changes: 2 additions & 1 deletion lib/browser/sources/FileSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export default class FileSource {
}

const value = this._file.slice(start, end)
return Promise.resolve({ value })
const done = end >= this.size
return Promise.resolve({ value, done })
}

close() {
Expand Down
4 changes: 2 additions & 2 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ interface UploadOptions {
overridePatchMethod?: boolean
headers?: { [key: string]: string }
addRequestId?: boolean
onBeforeRequest?: (req: HttpRequest) => void
onAfterResponse?: (req: HttpRequest, res: HttpResponse) => void
onBeforeRequest?: (req: HttpRequest) => void | Promise<void>
onAfterResponse?: (req: HttpRequest, res: HttpResponse) => void | Promise<void>

chunkSize?: number
retryDelays?: number[]
Expand Down
3 changes: 2 additions & 1 deletion lib/node/sources/BufferSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export default class BufferSource {
slice(start, end) {
const value = this._buffer.slice(start, end)
value.size = value.length
return Promise.resolve({ value })
const done = end >= this.size
return Promise.resolve({ value, done })
}

close() {}
Expand Down
5 changes: 3 additions & 2 deletions lib/node/sources/FileSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ class FileSource {
end: offset + end - 1,
autoClose: true,
})
stream.size = end - start
return Promise.resolve({ value: stream })
stream.size = Math.min(end - start, this.size)
const done = stream.size >= this.size
return Promise.resolve({ value: stream, done })
}

close() {
Expand Down
21 changes: 19 additions & 2 deletions lib/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ class BaseUpload {
constructor(file, options) {
// Warn about removed options from previous versions
if ('resume' in options) {
// eslint-disable-next-line no-console
console.log(
'tus: The `resume` option has been removed in tus-js-client v2. Please use the URL storage API instead.'
) // eslint-disable-line no-console
)
}

// The default options will already be added from the wrapper classes.
Expand Down Expand Up @@ -799,14 +800,30 @@ class BaseUpload {
}

return this._source.slice(start, end).then(({ value, done }) => {
const valueSize = value && value.size ? value.size : 0

// If the upload length is deferred, the upload size was not specified during
// upload creation. So, if the file reader is done reading, we know the total
// upload size and can tell the tus server.
if (this.options.uploadLengthDeferred && done) {
this._size = this._offset + (value && value.size ? value.size : 0)
this._size = this._offset + valueSize
req.setHeader('Upload-Length', this._size)
}

// The specified uploadSize might not match the actual amount of data that a source
// provides. In these cases, we cannot successfully complete the upload, so we
// rather error out and let the user know. If not, tus-js-client will be stuck
// in a loop of repeating empty PATCH requests.
// See https://community.transloadit.com/t/how-to-abort-hanging-companion-uploads/16488/13
const newSize = this._offset + valueSize
if (!this.options.uploadLengthDeferred && done && newSize !== this._size) {
return Promise.reject(
new Error(
`upload was configured with a size of ${this._size} bytes, but the source is done after ${newSize} bytes`
)
)
}

if (value === null) {
return this._sendRequest(req)
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tus-js-client",
"version": "3.1.0",
"version": "3.1.1",
"description": "A pure JavaScript client for the tus resumable upload protocol",
"main": "lib.es5/node/index.js",
"module": "lib.esm/node/index.js",
Expand Down
45 changes: 45 additions & 0 deletions test/spec/test-browser-specific.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,51 @@ describe('tus', () => {

await options.onSuccess.toBeCalled
})

it('should throw an error if the source provides less data than uploadSize', async () => {
const reader = makeReader('hello world')

const testStack = new TestHttpStack()
const options = {
httpStack: testStack,
uploadSize: 100,
chunkSize: 100,
endpoint: 'http://tus.io/uploads',
retryDelays: [],
onError: waitableFunction('onError'),
}

const upload = new tus.Upload(reader, options)
upload.start()
let req = await testStack.nextRequest()
expect(req.url).toBe('http://tus.io/uploads')
expect(req.method).toBe('POST')
expect(req.requestHeaders['Tus-Resumable']).toBe('1.0.0')

req.respondWith({
status: 204,
responseHeaders: {
Location: 'http://tus.io/uploads/foo',
},
})

req = await testStack.nextRequest()
expect(req.url).toBe('http://tus.io/uploads/foo')
expect(req.method).toBe('PATCH')

req.respondWith({
status: 204,
responseHeaders: {
'Upload-Offset': 11,
},
})

const err = await options.onError.toBeCalled

expect(err.message).toBe(
'tus: failed to upload chunk at offset 11, caused by Error: upload was configured with a size of 100 bytes, but the source is done after 11 bytes, originated from request (method: PATCH, url: http://tus.io/uploads/foo, response code: n/a, response text: n/a, request id: n/a)'
)
})
})

describe('resolving of URIs', () => {
Expand Down
32 changes: 32 additions & 0 deletions test/spec/test-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,38 @@ describe('tus', () => {
)
})

it('should throw an error if the source provides less data than uploadSize', async () => {
const testStack = new TestHttpStack()
const file = getBlob('hello world')
const options = {
httpStack: testStack,
uploadSize: 100,
endpoint: 'http://tus.io/uploads',
retryDelays: [],
onError: waitableFunction('onError'),
}

const upload = new tus.Upload(file, options)
upload.start()

const req = await testStack.nextRequest()
expect(req.url).toBe('http://tus.io/uploads')
expect(req.method).toBe('POST')
expect(req.requestHeaders['Tus-Resumable']).toBe('1.0.0')

req.respondWith({
status: 204,
responseHeaders: {
Location: 'http://tus.io/uploads/foo',
},
})

const err = await options.onError.toBeCalled
expect(err.message).toBe(
'tus: failed to upload chunk at offset 0, caused by Error: upload was configured with a size of 100 bytes, but the source is done after 11 bytes, originated from request (method: PATCH, url: http://tus.io/uploads/foo, response code: n/a, response text: n/a, request id: n/a)'
)
})

it('should throw if retryDelays is not an array', () => {
const file = getBlob('hello world')
const upload = new tus.Upload(file, {
Expand Down
Loading

0 comments on commit e1f9cc7

Please sign in to comment.