@sphereon/did-auth-siop
Version:
Self Issued OpenID V2 (SIOPv2) and OpenID 4 Verifiable Presentations (OID4VP)
139 lines (124 loc) • 4.48 kB
text/typescript
import { fetch } from 'cross-fetch'
import Debug from 'debug'
import { ContentType, SIOPErrors, SIOPResonse } from '../types'
const debug = Debug('sphereon:siopv2:http')
export const getJson = async <T>(
URL: string,
opts?: {
bearerToken?: string
contentType?: string | ContentType
accept?: string
customHeaders?: HeadersInit
exceptionOnHttpErrorStatus?: boolean
},
): Promise<SIOPResonse<T>> => {
return await siopFetch(URL, undefined, { method: 'GET', ...opts })
}
export const formPost = async <T>(
url: string,
body: BodyInit,
opts?: {
bearerToken?: string
contentType?: string | ContentType
accept?: string
customHeaders?: HeadersInit
exceptionOnHttpErrorStatus?: boolean
},
): Promise<SIOPResonse<T>> => {
return await post(url, body, opts?.contentType ? { ...opts } : { contentType: ContentType.FORM_URL_ENCODED, ...opts })
}
export const post = async <T>(
url: string,
body?: BodyInit,
opts?: {
bearerToken?: string
contentType?: string | ContentType
accept?: string
customHeaders?: HeadersInit
exceptionOnHttpErrorStatus?: boolean
},
): Promise<SIOPResonse<T>> => {
return await siopFetch(url, body, { method: 'POST', ...opts })
}
const siopFetch = async <T>(
url: string,
body?: BodyInit,
opts?: {
method?: string
bearerToken?: string
contentType?: string | ContentType
accept?: string
customHeaders?: HeadersInit
exceptionOnHttpErrorStatus?: boolean
},
): Promise<SIOPResonse<T>> => {
if (!url || url.toLowerCase().startsWith('did:')) {
throw Error(`Invalid URL supplied. Expected a http(s) URL. Recieved: ${url}`)
}
const headers: Record<string, any> = opts?.customHeaders ? opts.customHeaders : {}
if (opts?.bearerToken) {
headers['Authorization'] = `Bearer ${opts.bearerToken}`
}
const method = opts?.method ? opts.method : body ? 'POST' : 'GET'
const accept = opts?.accept ? opts.accept : 'application/json'
headers['Content-Type'] = opts?.contentType ? opts.contentType : method !== 'GET' ? 'application/json' : undefined
headers['Accept'] = accept
const payload: RequestInit = {
method,
headers,
body,
}
debug(`START fetching url: ${url}`)
if (body) {
debug(`Body:\r\n${JSON.stringify(body)}`)
}
debug(`Headers:\r\n${JSON.stringify(payload.headers)}`)
const origResponse = await fetch(url, payload)
const clonedResponse = origResponse.clone()
const success = origResponse && origResponse.status >= 200 && origResponse.status < 400
const textResponseBody = await clonedResponse.text()
const isJSONResponse =
(accept === 'application/json' || origResponse.headers.get('Content-Type') === 'application/json') && textResponseBody.trim().startsWith('{')
const responseBody = isJSONResponse ? JSON.parse(textResponseBody) : textResponseBody
if (success || opts?.exceptionOnHttpErrorStatus) {
debug(`${success ? 'success' : 'error'} status: ${clonedResponse.status}, body:\r\n${JSON.stringify(responseBody)}`)
} else {
console.warn(`${success ? 'success' : 'error'} status: ${clonedResponse.status}, body:\r\n${JSON.stringify(responseBody)}`)
}
if (!success && opts?.exceptionOnHttpErrorStatus) {
const error = JSON.stringify(responseBody)
throw new Error(error === '{}' ? '{"error": "not found"}' : error)
}
debug(`END fetching url: ${url}`)
return {
origResponse,
successBody: success ? responseBody : undefined,
errorBody: !success ? responseBody : undefined,
}
}
export const getWithUrl = async <T>(url: string, textResponse?: boolean): Promise<T> => {
// try {
const response = await fetch(url)
if (response.status >= 400) {
return Promise.reject(Error(`${SIOPErrors.RESPONSE_STATUS_UNEXPECTED} ${response.status}:${response.statusText} URL: ${url}`))
}
if (textResponse === true) {
return (await response.text()) as unknown as T
}
return await response.json()
/*} catch (e) {
return Promise.reject(Error(`${(e as Error).message}`));
}*/
}
export const fetchByReferenceOrUseByValue = async <T>(referenceURI: string, valueObject: T, textResponse?: boolean): Promise<T> => {
let response: T = valueObject
if (referenceURI) {
try {
response = await getWithUrl(referenceURI, textResponse)
} catch (e) {
console.log(e)
throw new Error(`${SIOPErrors.REG_PASS_BY_REFERENCE_INCORRECTLY}: ${(e as Error).message}, URL: ${referenceURI}`)
}
}
return response
}