@copilotkit/runtime
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
83 lines (81 loc) • 3.09 kB
JavaScript
require("reflect-metadata");
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
const require_node_fetch_handler = require('./node-fetch-handler.cjs');
let _copilotkit_shared = require("@copilotkit/shared");
let _remix_run_node_fetch_server = require("@remix-run/node-fetch-server");
//#region src/v2/runtime/endpoints/express-fetch-bridge.ts
const METHODS_WITHOUT_BODY = new Set([
"GET",
"HEAD",
"OPTIONS"
]);
/**
* Creates a Node HTTP handler from a fetch handler, with Express body-parser
* compatibility. Use this instead of `createNodeFetchHandler` in Express adapters.
*
* When the body stream hasn't been consumed, delegates to the generic
* `createCopilotNodeHandler`. Only intercepts when Express middleware has
* pre-parsed the body.
*/
function createExpressNodeHandler(handler) {
const nodeHandler = require_node_fetch_handler.createCopilotNodeHandler(handler);
return async (req, res) => {
const method = (req.method ?? "GET").toUpperCase();
if (METHODS_WITHOUT_BODY.has(method) || !hasPreParsedBody(req)) return nodeHandler(req, res);
try {
await (0, _remix_run_node_fetch_server.sendResponse)(res, await handler(buildPreParsedRequest(req, res)));
} catch (err) {
_copilotkit_shared.logger.error({ err }, "Error in Express fetch bridge (pre-parsed path)");
if (!res.headersSent) {
res.statusCode = 500;
res.end("Internal Server Error");
}
}
};
}
/**
* Build a Fetch Request from a Node IncomingMessage whose body stream has
* already been consumed by an Express body parser.
*/
function buildPreParsedRequest(req, res) {
const expressReq = req;
const method = (req.method ?? "GET").toUpperCase();
const url = `${req.protocol || "http"}://${req.headers.host ?? "localhost"}${req.originalUrl ?? req.url ?? ""}`;
const headers = new Headers();
for (const [key, value] of Object.entries(req.headers)) {
if (value === void 0) continue;
if (Array.isArray(value)) for (const v of value) headers.append(key, v);
else headers.set(key, value);
}
const controller = new AbortController();
res.on("close", () => {
if (!res.writableFinished) controller.abort();
});
const init = {
method,
headers,
signal: controller.signal
};
const { body, contentType } = synthesizeBody(expressReq.body);
if (contentType) headers.set("content-type", contentType);
headers.delete("content-length");
if (body !== void 0) init.body = body;
return new Request(url, init);
}
function hasPreParsedBody(req) {
if (req.body === void 0 || req.body === null) return false;
const state = req._readableState;
return Boolean(req.readableEnded || req.complete || state?.ended || state?.endEmitted);
}
function synthesizeBody(body) {
if (Buffer.isBuffer(body) || body instanceof Uint8Array) return { body };
if (typeof body === "string") return { body };
if (typeof body === "object" && body !== null) return {
body: JSON.stringify(body),
contentType: "application/json"
};
return {};
}
//#endregion
exports.createExpressNodeHandler = createExpressNodeHandler;
//# sourceMappingURL=express-fetch-bridge.cjs.map