Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Commit

Permalink
fix: let gaxios handle API errors (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus authored and JustinBeckwith committed Aug 15, 2019
1 parent 4bd3d50 commit 7a913ef
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"linkinator": "^1.5.0",
"mocha": "^6.1.4",
"mockery": "^2.1.0",
"nock": "^10.0.0",
"nock": "^11.0.0",
"sinon": "^7.3.2",
"source-map-support": "^0.5.6",
"typescript": "~3.5.0"
Expand Down
20 changes: 10 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ export interface UploadConfig {
}

export interface ConfigMetadata {
// tslint:disable-next-line no-any
[key: string]: any;

/**
* Set the length of the file being uploaded.
*/
Expand Down Expand Up @@ -505,21 +508,18 @@ export class Upload extends Pumpify {
reqOpts.params = reqOpts.params || {};
reqOpts.params.userProject = this.userProject;
}
reqOpts.validateStatus = () => true;
// Let gaxios know we will handle a 308 error code ourselves.
reqOpts.validateStatus = (status: number) => {
return (
(status >= 200 && status < 300) ||
status === RESUMABLE_INCOMPLETE_STATUS_CODE
);
};

const res = await this.authClient.request(reqOpts);
if (res.data && res.data.error) {
throw res.data.error;
}
// If no error was returned, but the response had an invalid status
// code, create a new error to be passed to the callback.
if (
(res.status < 200 || res.status >= 300) &&
res.status !== RESUMABLE_INCOMPLETE_STATUS_CODE
) {
const e = new Error(`The request failed with a ${res.status}.`);
(e as ErrorWithCode).code = res.status;
}
return res;
}

Expand Down
39 changes: 32 additions & 7 deletions system-test/kitchen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@
import * as assert from 'assert';
import * as fs from 'fs';
import {Readable} from 'stream';
import {createURI, upload} from '../src';
import {createURI, ErrorWithCode, upload} from '../src';

const bucketName = process.env.BUCKET_NAME || 'gcs-resumable-upload-test';
const fileName = 'daw.jpg';

describe('end to end', () => {
beforeEach(() => {
upload({bucket: bucketName, file: fileName}).deleteConfig();
});

it('should work', done => {
let uploadSucceeded = false;
fs.createReadStream('daw.jpg')
fs.createReadStream(fileName)
.on('error', done)
.pipe(
upload({
bucket: bucketName,
file: 'daw.jpg',
file: fileName,
metadata: {contentType: 'image/jpg'},
})
)
Expand All @@ -35,7 +40,7 @@ describe('end to end', () => {
});

it('should resume an interrupted upload', done => {
fs.stat('daw.jpg', (err, fd) => {
fs.stat(fileName, (err, fd) => {
assert.ifError(err);

const size = fd.size;
Expand All @@ -51,11 +56,11 @@ describe('end to end', () => {

const ws = upload({
bucket: bucketName,
file: 'daw.jpg',
file: fileName,
metadata: {contentType: 'image/jpg'},
});

fs.createReadStream('daw.jpg')
fs.createReadStream(fileName)
.on('error', callback)
.on('data', function(this: Readable, chunk) {
sizeStreamed += chunk.length;
Expand Down Expand Up @@ -88,10 +93,30 @@ describe('end to end', () => {
createURI(
{
bucket: bucketName,
file: 'daw.jpg',
file: fileName,
metadata: {contentType: 'image/jpg'},
},
done
);
});

it('should return a non-resumable failed upload', done => {
const metadata = {
metadata: {largeString: 'a'.repeat(2.1e6)},
};

fs.createReadStream(fileName)
.on('error', done)
.pipe(
upload({
bucket: bucketName,
file: fileName,
metadata,
})
)
.on('error', (err: ErrorWithCode) => {
assert.strictEqual(err.code, '400');
done();
});
});
});
37 changes: 19 additions & 18 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,13 +841,25 @@ describe('gcs-resumable-upload', () => {
scopes.forEach(x => x.done());
});

it('should execute the callback with error & response if one occurred', async () => {
const scope = mockAuthorizeRequest(500, ':(');
await assertRejects(
up.makeRequest({}),
/Request failed with status code 500/
);
scope.done();
it('should set validate status', done => {
up.authClient = {
request: (reqOpts: GaxiosOptions) => {
assert.strictEqual(reqOpts.validateStatus!(100), false);
assert.strictEqual(reqOpts.validateStatus!(199), false);
assert.strictEqual(reqOpts.validateStatus!(300), false);
assert.strictEqual(reqOpts.validateStatus!(400), false);
assert.strictEqual(reqOpts.validateStatus!(500), false);

assert.strictEqual(reqOpts.validateStatus!(200), true);
assert.strictEqual(reqOpts.validateStatus!(299), true);
assert.strictEqual(reqOpts.validateStatus!(308), true);

done();

return {};
},
};
up.makeRequest(REQ_OPTS);
});

it('should make the correct request', async () => {
Expand All @@ -863,17 +875,6 @@ describe('gcs-resumable-upload', () => {
assert.deepStrictEqual(res.headers, {});
});

it('should execute the callback with error & response', async () => {
const response = {body: 'wooo'};
mockAuthorizeRequest();
const scope = nock(REQ_OPTS.url!)
.get(queryPath)
.reply(500, response.body);
const resp = await up.makeRequest(REQ_OPTS);
assert.strictEqual(resp.data, response.body);
scope.done();
});

it('should execute the callback with a body error & response', async () => {
const error = new GaxiosError(
'Error message',
Expand Down

0 comments on commit 7a913ef

Please sign in to comment.