Skip to content

Commit

Permalink
feat: add custom user agent
Browse files Browse the repository at this point in the history
  • Loading branch information
pviti committed Nov 30, 2023
1 parent ad11d18 commit fe2050d
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 48 deletions.
38 changes: 19 additions & 19 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
















import type { Resource, ResourceRel } from './resource'
import type { VersionType } from './resources/versions'

Expand Down
53 changes: 42 additions & 11 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { InterceptorManager } from './interceptor'
import config from './config'
import type { Agent as HttpAgent } from 'http'
import type { Agent as HttpsAgent } from 'https'
// import { packageInfo } from './util'

import Debug from './debug'
const debug = Debug('client')
Expand All @@ -25,20 +26,25 @@ type RequestHeaders = Record<string, string>

// Subset of AxiosRequestConfig
type RequestConfig = {
timeout?: number;
params?: RequestParams;
httpAgent?: HttpAgent;
httpsAgent?: HttpsAgent;
proxy?: ProxyConfig;
timeout?: number
params?: RequestParams
httpAgent?: HttpAgent
httpsAgent?: HttpsAgent
proxy?: ProxyConfig
headers?: RequestHeaders
}

type RequestConfigExtra = {
adapter?: Adapter
userAgent?: string
}

type ApiConfig = {
domain?: string,
accessToken: string
}

type ApiClientInitConfig = ApiConfig & RequestConfig & { adapter?: Adapter }
type ApiClientInitConfig = ApiConfig & RequestConfig & RequestConfigExtra
type ApiClientConfig = Partial<ApiClientInitConfig>


Expand Down Expand Up @@ -67,20 +73,26 @@ class ApiClient {
timeout: options.timeout || config.client.timeout,
proxy: options.proxy,
httpAgent: options.httpAgent,
httpsAgent: options.httpsAgent,
httpsAgent: options.httpsAgent
}

// Set custom headers
const customHeaders = this.customHeaders(options.headers)

// Set User-Agent
// const userAgentData = packageInfo(['version', 'dependencies.axios'], { nestedName: true })
let userAgent = options.userAgent || `SDK-provisioning axios/${axios.VERSION}`
if (!userAgent.includes('axios/')) userAgent += ` axios/${axios.VERSION}`

const axiosOptions: CreateAxiosDefaults = {
baseURL: this.baseUrl,
timeout: config.client.timeout,
headers: {
...customHeaders,
'Accept': 'application/vnd.api+json',
'Content-Type': 'application/vnd.api+json',
'Authorization': 'Bearer ' + this.#accessToken
'Authorization': 'Bearer ' + this.#accessToken,
'User-Agent': userAgent
},
...axiosConfig
}
Expand Down Expand Up @@ -108,19 +120,35 @@ class ApiClient {
if (config.httpAgent) def.httpAgent = config.httpAgent
if (config.httpsAgent) def.httpsAgent = config.httpsAgent

if (config.adapter) this.adapter(config.adapter)
if (config.userAgent) this.userAgent(config.userAgent)


// API Client config
if (config.accessToken) {
this.#accessToken = config.accessToken
def.headers.common.Authorization = 'Bearer ' + this.#accessToken;
}
if (config.headers) def.headers.common = this.customHeaders(config.headers)
if (config.adapter) this.adapter(config.adapter)

return this

}


userAgent(userAgent: string): ApiClient {
if (userAgent) {
let ua = userAgent
if (!ua.includes('axios/')) {
// const axiosVer = packageInfo(['dependencies.axios'], { nestedName: true })
if (axios.VERSION) ua += ` axios/${axios.VERSION}`
}
this.#client.defaults.headers['User-Agent'] = ua
}
return this
}


adapter(adapter: Adapter): ApiClient {
if (adapter) this.#client.defaults.adapter = adapter
return this
Expand All @@ -131,11 +159,14 @@ class ApiClient {

debug('request %s %s, %O, %O', method, path, body || {}, options || {})

// Ignored params alerts (in debug mode)
if (options?.adapter) debug('Adapter ignored in request config')
if (options?.userAgent) debug('User-Agent header ignored in request config')

const data = body ? { data: body } : undefined
const url = path

// Runtime request parameters
// const baseUrl = options?.organization ? baseURL(options.organization, options.domain) : undefined
const accessToken = options?.accessToken || this.#accessToken

const headers = this.customHeaders(options?.headers)
Expand All @@ -158,7 +189,7 @@ class ApiClient {
const customHeaders: RequestHeaders = {}
if (headers) {
for (const [name, value] of Object.entries(headers))
if (!['accept', 'content-type', 'authorization'].includes(name.toLowerCase())) customHeaders[name] = value
if (!['accept', 'content-type', 'authorization', 'user-agent'].includes(name.toLowerCase())) customHeaders[name] = value
}
return customHeaders
}
Expand Down
32 changes: 30 additions & 2 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ObjectType } from "../src/common";
import type { ObjectType } from "../src/common"
// import path from 'path'



Expand All @@ -15,5 +16,32 @@ const sortObjectFields = (obj: ObjectType): ObjectType => {
return sorted
}

/*
const nestedField = (obj: any, field: string): { key: string, val: any } => {
export { sleep, sortObjectFields }
let fp = field
if (fp.endsWith('.')) fp = fp.substring(0, fp.length-1)
const dots = field.split(".")
const key = dots[dots.length-1]
let val = obj
while (dots.length && (val = val[dots.shift() || '']));
return { key, val }
}
*/

/*
const packageInfo = (fields?: string | string[], options?: any): Record<string, any> => {
const pjson = require(path.resolve('./', 'package.json'))
return fields? (Array.isArray(fields)? fields : [ fields ]).reduce((info: any, field) => {
const nf = nestedField(pjson, field)
info[options?.nestedName? nf.key : field] = nf.val
return info
}, {}) : pjson
}
*/


export { sleep, sortObjectFields, /* packageInfo */ }

0 comments on commit fe2050d

Please sign in to comment.