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

65 lines
1.7 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: RequestHandler = async (req, res, next) => {
if (Number(req.headers["content-length"] ?? 0) === 0) {
next();
return;
}
const isUsingDfi = req.headers.pragma?.toUpperCase() === "DFI";
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("=")));
const originalSend = res.send;
res.send = (params) => {
const body =
typeof params === "object"
? `${Object.entries(params)
.map(([k, v]) => `${k}=${v}`)
.join("&")}\n`
: params;
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();
};