Files
l2-market-parser/vite.config.js
T

93 lines
2.9 KiB
JavaScript

import { defineConfig, loadEnv } from "vite";
const MAX_BATCH_BYTES = 96 * 1024;
const L2_MARKET_IMPORT_TOKEN = "ebc212a3735eddf2b3ce7bcaf01522e2d53425483436ff1814e7998a8bde8d0e";
export async function forwardMarketBatch(body, { url, token, fetchImpl = fetch }) {
if (!url || !token) return new Response("Market import is not configured", { status: 503 });
return fetchImpl(url, {
method: "POST",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
body,
redirect: "error",
signal: AbortSignal.timeout(15_000),
});
}
export function rejectNonLocalRequest(request) {
const rawContentType = request.headers["content-type"];
const contentType = typeof rawContentType === "string" ? rawContentType.split(";", 1)[0].trim().toLowerCase() : "";
if (contentType !== "application/json") return 415;
const host = typeof request.headers.host === "string" ? request.headers.host : "";
return request.headers.origin === `http://${host}` ? null : 403;
}
function marketImportProxy(options) {
return {
name: "market-import-proxy",
configureServer(server) {
server.middlewares.use("/api/market-import", async (request, response) => {
if (request.method !== "POST") {
response.statusCode = 405;
response.end();
return;
}
const rejection = rejectNonLocalRequest(request);
if (rejection) {
response.statusCode = rejection;
response.end();
return;
}
try {
const body = await readBody(request);
const upstream = await forwardMarketBatch(body, options);
response.statusCode = upstream.status;
response.setHeader("Content-Type", upstream.headers.get("content-type") || "application/json");
response.end(await upstream.text());
} catch (error) {
response.statusCode = error.code === "BATCH_TOO_LARGE" ? 413 : 502;
response.end(error.code === "BATCH_TOO_LARGE" ? "Batch too large" : "Market import failed");
}
});
},
};
}
function readBody(request) {
return new Promise((resolve, reject) => {
const chunks = [];
let size = 0;
let tooLarge = false;
request.on("data", (chunk) => {
if (tooLarge) return;
size += chunk.length;
if (size > MAX_BATCH_BYTES) {
tooLarge = true;
const error = new Error("Batch too large");
error.code = "BATCH_TOO_LARGE";
reject(error);
return;
}
chunks.push(chunk);
});
request.on("end", () => {
if (!tooLarge) resolve(Buffer.concat(chunks).toString("utf8"));
});
request.on("error", reject);
});
}
export default defineConfig(({ mode }) => {
const environment = loadEnv(mode, process.cwd(), "");
return {
base: "./",
plugins: [
marketImportProxy({
url: environment.L2_MARKET_IMPORT_URL,
token: L2_MARKET_IMPORT_TOKEN,
}),
],
};
});