47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import { Request, Response } from 'express';
|
|
|
|
export type UpstreamFetch = typeof fetch;
|
|
|
|
/**
|
|
* After zappier meters the call, forward Verae operations to middleware.
|
|
* When ZAPPIER_UPSTREAM is unset, callers keep the local mock.
|
|
*/
|
|
export async function proxyVerae(
|
|
req: Request,
|
|
res: Response,
|
|
pathname: string,
|
|
fetchImpl: UpstreamFetch = fetch,
|
|
): Promise<boolean> {
|
|
const base = (process.env.ZAPPIER_UPSTREAM || '').replace(/\/$/, '');
|
|
if (!base) return false;
|
|
const url = new URL(pathname, `${base}/`);
|
|
for (const [k, v] of Object.entries(req.query)) {
|
|
if (typeof v === 'string') url.searchParams.set(k, v);
|
|
}
|
|
const headers: Record<string, string> = { accept: 'application/json' };
|
|
const key = req.header('x-api-key');
|
|
if (key) headers['x-api-key'] = key;
|
|
const auth = req.header('authorization');
|
|
if (auth) headers.authorization = auth;
|
|
const veraeUserId = req.customer?.veraeUserId;
|
|
if (veraeUserId) headers['x-verae-user-id'] = veraeUserId;
|
|
const method = req.method.toUpperCase();
|
|
const init: RequestInit = { method, headers };
|
|
if (method !== 'GET' && method !== 'HEAD') {
|
|
headers['content-type'] = 'application/json';
|
|
init.body = JSON.stringify(req.body ?? {});
|
|
}
|
|
const r = await fetchImpl(url.toString(), init);
|
|
const text = await r.text();
|
|
let body: unknown = text;
|
|
try {
|
|
body = text ? JSON.parse(text) : {};
|
|
} catch {
|
|
/* keep text */
|
|
}
|
|
if (body && typeof body === 'object' && !Array.isArray(body) && res.locals.quote) {
|
|
(body as Record<string, unknown>).quote = res.locals.quote;
|
|
}
|
|
res.status(r.status).json(body);
|
|
return true;
|
|
}
|