@scalar/api-client
Version:
the open source API testing client
127 lines (125 loc) • 5.28 kB
JavaScript
import { ERRORS as P, normalizeError as U } from "../errors.js";
import { normalizeHeaders as N } from "../normalize-headers.js";
import { createFetchBody as Z } from "./create-fetch-body.js";
import { createFetchHeaders as $ } from "./create-fetch-headers.js";
import { createFetchQueryParams as M } from "./create-fetch-query-params.js";
import { decodeBuffer as ee } from "./decode-buffer.js";
import { setRequestCookies as oe, getCookieHeader as te } from "./set-request-cookies.js";
import { replaceTemplateVariables as h } from "../string-template.js";
import { isElectron as q } from "../electron.js";
import { isDefined as re, mergeUrls as se, shouldUseProxy as D, redirectToProxy as ne, httpStatusCodes as ae } from "@scalar/oas-utils/helpers";
import { buildRequestSecurity as ie } from "./build-request-security.js";
const Ce = ({
environment: E,
example: a,
globalCookies: L,
proxyUrl: u,
request: i,
securitySchemes: z,
selectedSecuritySchemeUids: B = [],
server: d,
status: o,
pluginManager: f
}) => {
try {
const t = E ?? {}, w = new AbortController(), R = a.parameters.path.reduce((e, s) => (s.enabled && (e[s.key] = h(s.value, t)), e), {}), F = h((d == null ? void 0 : d.url) ?? "", t), p = h(h(i.path, t), R);
let n = F || p;
if (!n)
throw P.URL_EMPTY;
Object.entries((d == null ? void 0 : d.variables) ?? {}).forEach(([e, s]) => {
n = h(n, {
[e]: R[e] || s.default
});
});
const _ = M(a, t, i), O = $(a, t), { body: W } = Z(i.method, a, t), { cookieParams: x } = oe({
example: a,
env: t,
globalCookies: L,
serverUrl: n,
proxyUrl: u
}), A = B.flat().map((e) => z[e]).filter(re), S = ie(A, t), c = { ...Object.entries(S.headers).reduce(
(e, [s, y]) => (e[s.toLowerCase()] = y, e),
{}
), ...O }, X = [...x, ...S.cookies], j = new URLSearchParams([..._, ...S.urlParams]);
q() && c["user-agent"] && (c["X-Scalar-User-Agent"] = c["user-agent"]), n = se(n, p, j);
const k = h(te(X, c.Cookie), t);
k && (q() || D(u, n) ? (console.warn(
"We're using a `X-Scalar-Cookie` custom header to the request. The proxy will forward this as a `Cookie` header. We do this to avoid the browser omitting the `Cookie` header for cross-origin requests for security reasons."
), c["X-Scalar-Cookie"] = k) : (console.warn(
`We're trying to add a Cookie header, but browsers often omit them for cross-origin requests for various security reasons. If it's not working, that's probably why. Here are the requirements for it to work:
- The browser URL must be on the same domain as the server URL.
- The connection must be made over HTTPS.
`
), c.Cookie = k));
const I = ne(u, n), b = new Request(I, {
method: i.method.toUpperCase(),
body: W ?? null,
headers: c
});
return [
null,
{
request: b,
sendRequest: async () => {
var s, y, C;
o == null || o.emit("start"), f && f.executeHook("onBeforeRequest", { request: b });
const e = Date.now();
try {
const r = await fetch(b, {
signal: w.signal
}), Q = (s = r.headers.get("content-type")) == null ? void 0 : s.startsWith("text/event-stream");
o == null || o.emit("stop");
const V = Date.now() - e, v = r.clone(), g = N(r.headers, D(u, n)), K = r.headers.get("content-type") ?? "text/plain;charset=UTF-8", T = await v.arrayBuffer(), Y = ee(T, K), m = r.clone(), G = m.statusText || ((y = ae[m.status]) == null ? void 0 : y.name) || "", J = [204, 205, 304].includes(m.status), l = new Response(J ? null : m.body, {
status: m.status,
statusText: G,
headers: m.headers
});
f && f.executeHook("onResponseReceived", { response: l, operation: i });
const H = "getSetCookie" in l.headers && typeof l.headers.getSetCookie == "function" ? l.headers.getSetCookie() : [];
return Q && r.body ? [
null,
{
timestamp: Date.now(),
request: a,
response: {
...l,
headers: g,
cookieHeaderKeys: H,
reader: (C = r.body) == null ? void 0 : C.getReader(),
duration: V,
method: i.method,
path: p
}
}
] : [
null,
{
timestamp: Date.now(),
request: a,
response: {
...r,
headers: g,
cookieHeaderKeys: H,
data: Y,
size: T.byteLength,
duration: Date.now() - e,
method: i.method,
status: r.status,
path: p
}
}
];
} catch (r) {
return o == null || o.emit("abort"), [U(r, P.REQUEST_FAILED), null];
}
},
controller: w
}
];
} catch (t) {
return console.error(t), o == null || o.emit("abort"), [U(t), null];
}
};
export {
Ce as createRequestOperation
};