67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
import iconv from "iconv-lite";
|
|
import getRawBody from "raw-body";
|
|
import { promisify } from "util";
|
|
import { inflate } from "zlib";
|
|
import type { RequestHandler } from "express";
|
|
|
|
const inflateAsync = promisify(inflate);
|
|
|
|
export const DFIRequestResponse: (mustUseDfi: boolean) => RequestHandler = (mustUseDfi) => {
|
|
return async (req, res, next) => {
|
|
if (Number(req.headers["content-length"] ?? 0) === 0) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
const isUsingDfi = req.headers.pragma?.toUpperCase() === "DFI";
|
|
|
|
if (mustUseDfi && !isUsingDfi) {
|
|
return res.status(200).send("");
|
|
}
|
|
|
|
const rawBody = await getRawBody(req, { encoding: "utf-8" });
|
|
|
|
let body: string;
|
|
|
|
if (isUsingDfi) {
|
|
const compressedBuffer = Buffer.from(rawBody, "base64");
|
|
const buffer = await inflateAsync(compressedBuffer);
|
|
|
|
body = buffer.toString("utf-8").trim();
|
|
} else {
|
|
body = rawBody.trim();
|
|
}
|
|
|
|
// Keys and values are not URL escaped.
|
|
// This should be fine. I think.
|
|
// eslint-disable-next-line require-atomic-updates
|
|
req.body = Object.fromEntries(body.split("&").map((s) => s.split("=")));
|
|
req.safeBody = req.body as Record<string, unknown>;
|
|
|
|
const originalSend = res.send;
|
|
|
|
res.send = (params) => {
|
|
const body = `${new URLSearchParams(params).toString()}\n`;
|
|
|
|
const encoding = req.body.encode ?? "EUC-JP";
|
|
const encodedBody = iconv.encode(body, encoding);
|
|
|
|
res.header("Content-Type", `text/plain; charset=${encoding}`);
|
|
|
|
// TODO: I don't know what black magic SEGA did, but I have been woefully
|
|
// unable to DFI-encode my responses...
|
|
return originalSend.apply(res, [encodedBody]);
|
|
|
|
// if (req.headers.pragma?.toUpperCase() !== "DFI") {
|
|
// return originalSend.apply(res, [encodedBody]);
|
|
// }
|
|
|
|
// res.header("Pragma", "DFI");
|
|
|
|
// return originalSend.apply(res, [deflateSync(encodedBody).toString("base64")]);
|
|
};
|
|
|
|
next();
|
|
};
|
|
};
|