gcs-resumable-upload
Advanced tools
Comparing version 0.14.1 to 1.0.0
@@ -135,3 +135,3 @@ /** | ||
private makeRequest; | ||
private getRequestStream; | ||
private makeRequestStream; | ||
private restart; | ||
@@ -138,0 +138,0 @@ private get; |
@@ -17,2 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const abort_controller_1 = require("abort-controller"); | ||
const ConfigStore = require("configstore"); | ||
@@ -22,6 +23,4 @@ const crypto_1 = require("crypto"); | ||
const Pumpify = require("pumpify"); | ||
const r = require("request"); | ||
const stream_1 = require("stream"); | ||
const streamEvents = require("stream-events"); | ||
const request = r.defaults({ json: true, pool: { maxSockets: Infinity } }); | ||
const BASE_URI = 'https://www.googleapis.com/upload/storage/v1/b'; | ||
@@ -146,28 +145,61 @@ const TERMINATED_UPLOAD_STATUS_CODE = 410; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const reqOpts = { | ||
method: 'PUT', | ||
url: this.uri, | ||
headers: { | ||
'Content-Range': 'bytes ' + this.offset + '-*/' + this.contentLength | ||
} | ||
}; | ||
const bufferStream = this.bufferStream = new stream_1.PassThrough(); | ||
// The buffer stream allows us to keep chunks in memory | ||
// until we are sure we can successfully resume the upload. | ||
const bufferStream = this.bufferStream || new stream_1.PassThrough(); | ||
this.bufferStream = bufferStream; | ||
// The offset stream allows us to analyze each incoming | ||
// chunk to analyze it against what the upstream API already | ||
// has stored for this upload. | ||
const offsetStream = this.offsetStream = | ||
new stream_1.PassThrough({ transform: this.onChunk.bind(this) }); | ||
new stream_1.Transform({ transform: this.onChunk.bind(this) }); | ||
// The delay stream gives us a chance to catch the response | ||
// from the API request before we signal to the user that | ||
// the upload was successful. | ||
const delayStream = new stream_1.PassThrough(); | ||
const requestStream = yield this.getRequestStream(reqOpts); | ||
this.setPipeline(bufferStream, offsetStream, requestStream, delayStream); | ||
// wait for "complete" from request before letting the stream finish | ||
// The request library (authClient.request()) requires the | ||
// stream to be sent within the request options. | ||
const requestStreamEmbeddedStream = new stream_1.PassThrough(); | ||
delayStream.on('prefinish', () => { | ||
// Pause the stream from finishing so we can process the | ||
// response from the API. | ||
this.cork(); | ||
}); | ||
requestStream.on('complete', resp => { | ||
if (resp.statusCode < 200 || resp.statusCode > 299) { | ||
// Process the API response to look for errors that came in | ||
// the response body. | ||
this.on('response', (resp) => { | ||
if (resp.data.error) { | ||
this.destroy(resp.data.error); | ||
return; | ||
} | ||
if (resp.status < 200 || resp.status > 299) { | ||
this.destroy(new Error('Upload failed')); | ||
return; | ||
} | ||
this.emit('metadata', resp.body); | ||
this.emit('metadata', resp.data); | ||
this.deleteConfig(); | ||
// Allow the stream to continue naturally so the user's | ||
// "finish" event fires. | ||
this.uncork(); | ||
}); | ||
this.setPipeline(bufferStream, offsetStream, delayStream); | ||
this.pipe(requestStreamEmbeddedStream); | ||
this.once('restart', () => { | ||
// The upload is being re-attempted. Disconnect the request | ||
// stream, so it won't receive more data. | ||
this.unpipe(requestStreamEmbeddedStream); | ||
}); | ||
const reqOpts = { | ||
method: 'PUT', | ||
url: this.uri, | ||
headers: { | ||
'Content-Range': 'bytes ' + this.offset + '-*/' + this.contentLength | ||
}, | ||
body: requestStreamEmbeddedStream, | ||
}; | ||
try { | ||
yield this.makeRequestStream(reqOpts); | ||
} | ||
catch (e) { | ||
this.destroy(e); | ||
} | ||
}); | ||
@@ -283,30 +315,19 @@ } | ||
} | ||
getRequestStream(reqOpts) { | ||
makeRequestStream(reqOpts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
if (this.userProject) { | ||
reqOpts.qs = reqOpts.qs || {}; | ||
reqOpts.qs.userProject = this.userProject; | ||
} | ||
const authHeaders = yield this.authClient.getRequestHeaders(reqOpts.url); | ||
reqOpts.headers = Object.assign({}, reqOpts.headers, authHeaders); | ||
const requestStream = request(reqOpts); | ||
requestStream.on('error', this.destroy.bind(this)); | ||
requestStream.on('response', this.onResponse.bind(this)); | ||
requestStream.on('complete', (resp) => { | ||
const body = resp.body; | ||
if (body && body.error) | ||
this.destroy(body.error); | ||
}); | ||
// this makes the response body come back in the response (weird?) | ||
requestStream.callback = () => { }; | ||
return requestStream; | ||
const controller = new abort_controller_1.default(); | ||
this.once('error', () => controller.abort()); | ||
if (this.userProject) { | ||
reqOpts.params = reqOpts.params || {}; | ||
reqOpts.params.userProject = this.userProject; | ||
} | ||
catch (e) { | ||
this.destroy(e); | ||
throw e; | ||
} | ||
reqOpts.signal = controller.signal; | ||
reqOpts.validateStatus = () => true; | ||
const res = yield this.authClient.request(reqOpts); | ||
this.onResponse(res); | ||
return res; | ||
}); | ||
} | ||
restart() { | ||
this.emit('restart'); | ||
this.numBytesWritten = 0; | ||
@@ -336,3 +357,3 @@ this.deleteConfig(); | ||
onResponse(resp) { | ||
if (resp.statusCode === 404) { | ||
if (resp.status === 404) { | ||
if (this.numRetries < RETRY_LIMIT) { | ||
@@ -347,3 +368,3 @@ this.numRetries++; | ||
} | ||
if (resp.statusCode > 499 && resp.statusCode < 600) { | ||
if (resp.status > 499 && resp.status < 600) { | ||
if (this.numRetries < RETRY_LIMIT) { | ||
@@ -350,0 +371,0 @@ const randomMs = Math.round(Math.random() * 1000); |
@@ -7,2 +7,38 @@ # Changelog | ||
## v1.0.0 | ||
02-28-2019 06:27 PST | ||
**This release has breaking changes**. The underlying transport library was changed from [request](https://github.com/request/request) to [gaxios](https://github.com/JustinBeckwith/gaxios). Any `response` objects returned via the API will now return a [`GaxiosResponse`](https://github.com/JustinBeckwith/gaxios/blob/88a47e000625d8192689acac5c40c0b1e1d963a2/src/gaxios.ts#L197-L203) object. | ||
#### Old Code | ||
```js | ||
.on('response', function (resp, metadata) { | ||
console.log(resp.statusCode); | ||
}) | ||
``` | ||
#### New Code | ||
```js | ||
.on('response', function (resp) { | ||
console.log(resp.status); | ||
}); | ||
``` | ||
### Implementation Changes | ||
- fix: replace request with gaxios ([#174](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/174)) | ||
### Documentation | ||
- docs: update links in contrib guide ([#184](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/184)) | ||
- docs: add lint/fix example to contributing guide ([#177](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/177)) | ||
### Internal / Testing Changes | ||
- chore(deps): update dependency mocha to v6 ([#185](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/185)) | ||
- build: use linkinator for docs test ([#183](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/183)) | ||
- build: create docs test npm scripts ([#182](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/182)) | ||
- build: test using @grpc/grpc-js in CI ([#181](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/181)) | ||
- chore: move CONTRIBUTING.md to root ([#179](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/179)) | ||
- chore(deps): update dependency typescript to ~3.3.0 ([#176](https://github.com/GoogleCloudPlatform/gcs-resumable-upload/pull/176)) | ||
## v0.14.1 | ||
@@ -9,0 +45,0 @@ |
{ | ||
"name": "gcs-resumable-upload", | ||
"version": "0.14.1", | ||
"version": "1.0.0", | ||
"description": "Upload a file to Google Cloud Storage with built-in resumable behavior", | ||
@@ -23,3 +23,5 @@ "repository": "googleapis/gcs-resumable-upload", | ||
"presystem-test": "npm run compile", | ||
"docs": "compodoc src/" | ||
"docs": "compodoc src/", | ||
"docs-test": "linkinator docs -r --skip www.googleapis.com", | ||
"predocs-test": "npm run docs" | ||
}, | ||
@@ -43,6 +45,7 @@ "keywords": [ | ||
"dependencies": { | ||
"abort-controller": "^2.0.2", | ||
"configstore": "^4.0.0", | ||
"gaxios": "^1.5.0", | ||
"google-auth-library": "^3.0.0", | ||
"pumpify": "^1.5.1", | ||
"request": "^2.87.0", | ||
"stream-events": "^1.0.4" | ||
@@ -62,3 +65,2 @@ }, | ||
"assert-rejects": "^1.0.0", | ||
"gaxios": "^1.2.2", | ||
"codecov": "^3.0.4", | ||
@@ -68,3 +70,3 @@ "gts": "^0.9.0", | ||
"is-stream": "^1.1.0", | ||
"mocha": "^5.2.0", | ||
"mocha": "^6.0.0", | ||
"mockery": "^2.1.0", | ||
@@ -75,4 +77,5 @@ "nock": "^10.0.0", | ||
"through2": "^3.0.0", | ||
"typescript": "~3.2.0" | ||
"typescript": "~3.3.0", | ||
"linkinator": "^1.1.2" | ||
} | ||
} |
@@ -192,3 +192,3 @@ # gcs-resumable-upload | ||
##### .on('response', function (resp, metadata) {}) | ||
##### .on('response', function (response) {}) | ||
@@ -199,3 +199,3 @@ ###### resp | ||
The HTTP response from [`request`](http://gitnpm.com/request). | ||
The [response object from Gaxios](https://github.com/JustinBeckwith/gaxios/blob/88a47e000625d8192689acac5c40c0b1e1d963a2/src/gaxios.ts#L197-L203). | ||
@@ -202,0 +202,0 @@ ###### metadata |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
50856
557
1
6
+ Addedabort-controller@^2.0.2
+ Addedgaxios@^1.5.0
+ Addedabort-controller@2.0.3(transitive)
- Removedrequest@^2.87.0
- Removedajv@6.12.6(transitive)
- Removedasn1@0.2.6(transitive)
- Removedassert-plus@1.0.0(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedaws-sign2@0.7.0(transitive)
- Removedaws4@1.13.2(transitive)
- Removedbcrypt-pbkdf@1.0.2(transitive)
- Removedcaseless@0.12.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcore-util-is@1.0.2(transitive)
- Removeddashdash@1.14.1(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removedecc-jsbn@0.1.2(transitive)
- Removedextsprintf@1.3.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedforever-agent@0.6.1(transitive)
- Removedform-data@2.3.3(transitive)
- Removedgetpass@0.1.7(transitive)
- Removedhar-schema@2.0.0(transitive)
- Removedhar-validator@5.1.5(transitive)
- Removedhttp-signature@1.2.0(transitive)
- Removedis-typedarray@1.0.0(transitive)
- Removedisstream@0.1.2(transitive)
- Removedjsbn@0.1.1(transitive)
- Removedjson-schema@0.4.0(transitive)
- Removedjson-schema-traverse@0.4.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedjsprim@1.4.2(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedoauth-sign@0.9.0(transitive)
- Removedperformance-now@2.1.0(transitive)
- Removedpsl@1.10.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqs@6.5.3(transitive)
- Removedrequest@2.88.2(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsshpk@1.18.0(transitive)
- Removedtough-cookie@2.5.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removedtweetnacl@0.14.5(transitive)
- Removeduri-js@4.4.1(transitive)
- Removeduuid@3.4.0(transitive)
- Removedverror@1.10.0(transitive)