Files
hoppscotch/packages/hoppscotch-common/src/helpers/network.ts
2023-12-04 23:31:49 +05:30

108 lines
2.5 KiB
TypeScript

import { AxiosRequestConfig } from "axios"
import { BehaviorSubject, Observable } from "rxjs"
import { cloneDeep } from "lodash-es"
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { HoppRESTResponse } from "./types/HoppRESTResponse"
import { EffectiveHoppRESTRequest } from "./utils/EffectiveURL"
import { getService } from "~/modules/dioc"
import {
InterceptorService,
NetworkResponse,
} from "~/services/interceptor.service"
export type NetworkStrategy = (
req: AxiosRequestConfig
) => TE.TaskEither<any, NetworkResponse>
export const cancelRunningRequest = () => {
// TODO: Implement
}
function processResponse(
res: NetworkResponse,
req: EffectiveHoppRESTRequest,
backupTimeStart: number,
backupTimeEnd: number,
successState: HoppRESTResponse["type"]
) {
const contentLength = res.headers["content-length"]
? parseInt(res.headers["content-length"])
: (res.data as ArrayBuffer).byteLength
return <HoppRESTResponse>{
type: successState,
statusCode: res.status,
statusText: res.statusText,
body: res.data,
headers: Object.keys(res.headers).map((x) => ({
key: x,
value: res.headers[x],
})),
meta: {
responseSize: contentLength,
responseDuration: backupTimeEnd - backupTimeStart,
},
req,
}
}
export function createRESTNetworkRequestStream(
request: EffectiveHoppRESTRequest
): [Observable<HoppRESTResponse>, () => void] {
const response = new BehaviorSubject<HoppRESTResponse>({
type: "loading",
req: request,
})
const req = cloneDeep(request)
const headers = req.effectiveFinalHeaders.reduce((acc, { key, value }) => {
return Object.assign(acc, { [key]: value })
}, {})
const params = new URLSearchParams()
for (const param of req.effectiveFinalParams) {
params.append(param.key, param.value)
}
const backupTimeStart = Date.now()
const service = getService(InterceptorService)
const res = service.runRequest({
method: req.method as any,
url: req.effectiveFinalURL.trim(),
headers,
params,
data: req.effectiveFinalBody,
})
res.response.then((res) => {
const backupTimeEnd = Date.now()
if (E.isRight(res)) {
const processedRes = processResponse(
res.right,
req,
backupTimeStart,
backupTimeEnd,
"success"
)
response.next(processedRes)
response.complete()
return
}
response.next({
type: "network_fail",
req,
error: res.left,
})
response.complete()
})
return [response, () => res.cancel()]
}