kozukata-toa/src/servers/allnet/middleware/dfi.ts

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();
};
};