diff --git a/packages/client/src/client.js b/packages/client/src/client.js index 013efce5d..d59d64905 100644 --- a/packages/client/src/client.js +++ b/packages/client/src/client.js @@ -94,19 +94,17 @@ export class PercyClient { // Performs a GET request for an API endpoint with appropriate headers. get(path) { return request(`${this.apiUrl}/${path}`, { - method: 'GET', - headers: this.headers() + headers: this.headers(), + method: 'GET' }); } // Performs a POST request to a JSON API endpoint with appropriate headers. post(path, body = {}) { return request(`${this.apiUrl}/${path}`, { + headers: this.headers({ 'Content-Type': 'application/vnd.api+json' }), method: 'POST', - body: JSON.stringify(body), - headers: this.headers({ - 'Content-Type': 'application/vnd.api+json' - }) + body }); } diff --git a/packages/client/src/request.js b/packages/client/src/request.js index a953498ed..3ccd54c4b 100644 --- a/packages/client/src/request.js +++ b/packages/client/src/request.js @@ -190,12 +190,28 @@ export function proxyAgentFor(url, options) { export function request(url, options = {}, callback) { // accept `request(url, callback)` if (typeof options === 'function') [options, callback] = [{}, options]; - let { body, retries, retryNotFound, interval, noProxy, ...requestOptions } = options; - // allow bypassing proxied requests entirely - if (!noProxy) requestOptions.agent ||= proxyAgentFor(url); - // parse the requested URL into request options + + // gather request options + let { body, headers, retries, retryNotFound, interval, noProxy, ...requestOptions } = options; let { protocol, hostname, port, pathname, search, hash } = new URL(url); + // automatically stringify body content + if (body && typeof body !== 'string') { + headers = { 'Content-Type': 'application/json', ...headers }; + body = JSON.stringify(body); + } + + // combine request options + Object.assign(requestOptions, { + agent: requestOptions.agent || + (!noProxy && proxyAgentFor(url)) || null, + path: pathname + search + hash, + protocol, + hostname, + headers, + port + }); + return retry((resolve, reject, retry) => { let handleError = error => { if (handleError.handled) return; @@ -203,8 +219,8 @@ export function request(url, options = {}, callback) { let shouldRetry = error.response // maybe retry 404s and always retry 500s - ? ((retryNotFound && error.response.status === 404) || - (error.response.status >= 500 && error.response.status < 600)) + ? ((retryNotFound && error.response.statusCode === 404) || + (error.response.statusCode >= 500 && error.response.statusCode < 600)) // retry specific error codes : (!!error.code && RETRY_ERROR_CODES.includes(error.code)); @@ -229,7 +245,11 @@ export function request(url, options = {}, callback) { } } catch (error) { handleError(Object.assign(error, { - response: { status: res.statusCode, body } + response: { + statusCode: res.statusCode, + headers: res.headers, + body + } })); } }; @@ -242,14 +262,7 @@ export function request(url, options = {}, callback) { res.on('error', handleError); }; - let req = (protocol === 'https:' ? https : http).request({ - ...requestOptions, - path: pathname + search + hash, - protocol, - hostname, - port - }); - + let req = (protocol === 'https:' ? https : http).request(requestOptions); req.on('response', handleResponse); req.on('error', handleError); req.end(body); diff --git a/packages/core/src/percy.js b/packages/core/src/percy.js index 1cb6d5014..48931f313 100644 --- a/packages/core/src/percy.js +++ b/packages/core/src/percy.js @@ -358,7 +358,7 @@ export class Percy { if (typeof options === 'function') options = await options(); await this.client.sendSnapshot(this.build.id, options); } catch (error) { - let failed = error.response?.status === 422 && ( + let failed = error.response?.statusCode === 422 && ( error.response.body.errors.find(e => ( e.source?.pointer === '/data/attributes/build' )));