Skip to content

Commit

Permalink
Merge 6bf99e4 into d99a762
Browse files Browse the repository at this point in the history
  • Loading branch information
altaywtf committed Jul 12, 2021
2 parents d99a762 + 6bf99e4 commit bd31ff9
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 38 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,21 @@
},
"prettier": "@putdotio/prettier-config",
"dependencies": {
"axios": "^0.19.2",
"axios": "^0.21.1",
"event-emitter": "^0.3.5",
"form-data": "^3.0.0",
"js-base64": "^2.6.2",
"qs": "^6.9.4",
"urijs": "^1.19.5"
"urijs": "^1.19.5",
"uuid": "^8.3.2"
},
"devDependencies": {
"@putdotio/prettier-config": "^1.0.0",
"@types/event-emitter": "^0.3.3",
"@types/js-base64": "^2.3.2",
"@types/qs": "^6.9.5",
"@types/urijs": "^1.19.13",
"@types/uuid": "^8.3.1",
"coveralls": "^3.1.0",
"husky": "^4.2.5",
"tsdx": "^0.14.1",
Expand Down
13 changes: 13 additions & 0 deletions src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import qs from 'qs'
import { v4 as uuidv4 } from 'uuid'
import { createClientIPChangeEmitterMiddleware } from '../middlewares/clientIPChangeEmitter'
import { createErrorEmitterMiddleware } from '../middlewares/errorEmitter'
import { createResponseFormatterMiddleware } from '../middlewares/responseFormatter'
Expand All @@ -14,6 +15,7 @@ import {
IPutioAPIClientOptions,
IPutioAPIClientResponse,
} from './types'
import { CORRELATION_ID_HEADER_NAME } from '../constants'
import Auth from '../resources/Auth/Auth'
import DownloadLinks from '../resources/DownloadLinks/DownloadLinks'
import Config from '../resources/Config'
Expand Down Expand Up @@ -170,6 +172,17 @@ export class PutioAPIClient {
qs.stringify(params, { arrayFormat: 'comma' }),
})

axiosInstance.interceptors.request.use(
config => {
config.headers[CORRELATION_ID_HEADER_NAME] = uuidv4()
return config
},
null,
// the 3rd argument is not reflected in the types, but it exists lol.
// @ts-ignore
{ synchronous: true },
)

const middlewareFactories: PutioAPIClientMiddlewareFactory[] = [
createResponseFormatterMiddleware,
createClientIPChangeEmitterMiddleware,
Expand Down
1 change: 1 addition & 0 deletions src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface IPutioAPIClientResponse<T> extends AxiosResponse {
}

export interface IPutioAPIClientErrorData {
correlation_id?: string
error_id?: string
error_uri?: string
error_type: string
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const CORRELATION_ID_HEADER_NAME = 'X-Putio-Correlation-Id'
21 changes: 19 additions & 2 deletions src/middlewares/responseFormatter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ describe('middlewares/responseFormatter', () => {
"foo": "bar",
"status": "OK",
},
"config": Object {},
"config": Object {
"headers": Object {
"X-Putio-Correlation-Id": "443bff25-b0fa-403b-88b0-00ae5a114b2e",
},
},
"data": Object {
"foo": "bar",
"status": "OK",
Expand Down Expand Up @@ -50,6 +54,7 @@ describe('middlewares/responseFormatter', () => {
responseFormatter.onRejected(error).catch(e =>
expect(e).toMatchInlineSnapshot(`
Object {
"correlation_id": "443bff25-b0fa-403b-88b0-00ae5a114b2e",
"error_message": "Putio API Error",
"error_type": "API_ERROR",
"status_code": 400,
Expand All @@ -58,7 +63,7 @@ describe('middlewares/responseFormatter', () => {
)
})

it('sets error.data property correctly when the request failed with HTTP response but without Put.io API signature', () => {
it('sets error.data property correctly when the request failed with HTTP response but without Put.io API signature and no meaningful header config', () => {
const error: IPutioAPIClientError = {
...mockPutioAPIClientError,
response: {
Expand All @@ -70,9 +75,12 @@ describe('middlewares/responseFormatter', () => {
},
}

error.config.headers = undefined

responseFormatter.onRejected(error).catch(e =>
expect(e).toMatchInlineSnapshot(`
Object {
"correlation_id": undefined,
"error_message": "AXIOS_ERROR_MESSAGE",
"error_type": "ERROR",
"status_code": 502,
Expand All @@ -85,6 +93,7 @@ describe('middlewares/responseFormatter', () => {
responseFormatter.onRejected(mockPutioAPIClientError).catch(e =>
expect(e).toMatchInlineSnapshot(`
Object {
"correlation_id": undefined,
"error_message": "AXIOS_ERROR_MESSAGE",
"error_type": "ERROR",
"status_code": 0,
Expand All @@ -93,4 +102,12 @@ describe('middlewares/responseFormatter', () => {
)
})
})

describe('royally fucked up cases', () => {
const royallyFuckedUpError = new Error('undefined is not a function')

responseFormatter
.onRejected(royallyFuckedUpError as any)
.catch(e => expect(e).toBe(royallyFuckedUpError))
})
})
32 changes: 20 additions & 12 deletions src/middlewares/responseFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import axios from 'axios'
import {
IPutioAPIClientError,
IPutioAPIClientErrorData,
PutioAPIClientMiddlewareFactory,
} from '../client/types'
import { CORRELATION_ID_HEADER_NAME } from '../constants'
import { isPutioAPIErrorResponse } from '../utils'

export const createResponseFormatterMiddleware: PutioAPIClientMiddlewareFactory = () => ({
Expand All @@ -10,25 +13,30 @@ export const createResponseFormatterMiddleware: PutioAPIClientMiddlewareFactory
body: response.data,
}),

onRejected: error => {
let errorData: any = {}
onRejected: (error: Error) => {
if (!axios.isAxiosError(error)) {
return Promise.reject(error)
}

let errorData: IPutioAPIClientErrorData = {
correlation_id: error.config.headers?.[CORRELATION_ID_HEADER_NAME],
error_message: error.message,
error_type: 'ERROR',
status_code: 0,
}

if (error.response && error.response.data) {
const { status, data } = error.response

errorData = isPutioAPIErrorResponse(data)
? { ...data, status_code: status }
? {
...errorData,
...data,
status_code: status,
}
: {
error_message: error.message,
error_type: 'ERROR',
...errorData,
status_code: status,
}
} else {
errorData = {
error_message: error.message,
error_type: 'ERROR',
status_code: 0,
}
}

const formattedError: IPutioAPIClientError = {
Expand Down
15 changes: 11 additions & 4 deletions src/test-utils/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { AxiosError } from 'axios'
import { AxiosError, AxiosRequestConfig } from 'axios'
import { CORRELATION_ID_HEADER_NAME } from '../constants'
import {
IPutioAPIClientError,
IPutioAPIClientErrorData,
IPutioAPIClientResponse,
} from '../client/types'

const mockRequestConfig: AxiosRequestConfig = {
headers: {
[CORRELATION_ID_HEADER_NAME]: '443bff25-b0fa-403b-88b0-00ae5a114b2e',
},
}

export const mockPutioAPIClientResponse: IPutioAPIClientResponse<{
foo: string
}> = {
config: {},
config: mockRequestConfig,
data: { foo: 'bar', status: 'OK' },
headers: {},
status: 200,
statusText: 'ok',
}

export const mockAxiosError: AxiosError = {
config: {},
config: mockRequestConfig,
isAxiosError: true,
name: 'AXIOS_ERROR',
message: 'AXIOS_ERROR_MESSAGE',
Expand Down Expand Up @@ -44,7 +51,7 @@ export const createMockResponse = <T>(
data: T,
status: number = 200,
): IPutioAPIClientResponse<T> => ({
config: {},
config: mockRequestConfig,
data: { ...data, status: 'OK' },
status,
headers: {},
Expand Down
37 changes: 19 additions & 18 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,11 @@
resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.13.tgz#0bd025b65df8ee5f038bbf6f1cb2e95160b49a56"
integrity sha512-Wg/E8Q+ylkR6JElTwOcjG7kM99/iJz28E9RKr8syOxssRs3gWchsziUkb+Nr254aUBWHY0QiScGAfIx4lKI3/g==

"@types/uuid@^8.3.1":
version "8.3.1"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==

"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
Expand Down Expand Up @@ -1751,12 +1756,12 @@ axe-core@^3.5.4:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227"
integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==

axios@^0.19.2:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "1.5.10"
follow-redirects "^1.10.0"

axobject-query@^2.1.2:
version "2.2.0"
Expand Down Expand Up @@ -2328,13 +2333,6 @@ data-urls@^1.1.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"

debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"

debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
Expand Down Expand Up @@ -3065,12 +3063,10 @@ flatted@^2.0.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==

follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.10.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==

for-in@^1.0.2:
version "1.0.2"
Expand Down Expand Up @@ -6281,6 +6277,11 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==

uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==

v8-compile-cache@^2.0.3:
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745"
Expand Down

0 comments on commit bd31ff9

Please sign in to comment.