mirror of
https://github.com/musistudio/claude-code-router.git
synced 2026-08-29 03:12:10 +08:00
Sanitize target model header while preserving Unicode body
This commit is contained in:
@@ -8,6 +8,7 @@ import { setTimeout as delay } from "node:timers/promises";
|
||||
import type { GatewayMediaProtocol } from "@ccr/core/contracts/app";
|
||||
import type { ImageEditRequest, ImageGenerateRequest, MediaExecutionContext, MediaExecutionResult, VideoGenerateRequest } from "@ccr/core/media/contracts";
|
||||
import { detectMediaType } from "@ccr/core/media/storage";
|
||||
import { sanitizeHeaderValue } from "@ccr/core/providers/runtime-topology";
|
||||
import { fetchWithSystemProxy } from "@ccr/core/proxy/system-proxy-fetch";
|
||||
|
||||
const maxApiArtifactBytes = 250 * 1024 * 1024;
|
||||
@@ -185,7 +186,7 @@ export class GatewayMediaExecutor {
|
||||
: {}),
|
||||
...(jsonBody ? { "content-type": "application/json" } : {}),
|
||||
...(idempotencyKey ? { "idempotency-key": idempotencyKey } : {}),
|
||||
"x-target-model": this.target.model,
|
||||
"x-target-model": sanitizeHeaderValue(this.target.model),
|
||||
"x-target-provider": this.target.providerSelector
|
||||
};
|
||||
}
|
||||
|
||||
@@ -118,6 +118,41 @@ test("media gateway errors expose the concrete failed provider attempt", async (
|
||||
);
|
||||
});
|
||||
|
||||
test("media gateway sanitizes target model header while preserving unicode body model", async (t) => {
|
||||
const rawModel = "「中文模型」image-model";
|
||||
let requestBody;
|
||||
let targetModelHeader;
|
||||
const server = createServer(async (request, response) => {
|
||||
if (request.method === "POST" && request.url === "/v1/images/generations") {
|
||||
targetModelHeader = request.headers["x-target-model"];
|
||||
requestBody = JSON.parse((await consume(request)).toString("utf8"));
|
||||
json(response, { data: [{ url: "https://media.example/artifact.png" }] });
|
||||
return;
|
||||
}
|
||||
response.writeHead(404).end();
|
||||
});
|
||||
if (!await listenOrSkip(t, server)) return;
|
||||
await waitForTcpListener(server);
|
||||
t.after(() => server.close());
|
||||
|
||||
const executor = new GatewayMediaExecutor({
|
||||
model: rawModel,
|
||||
protocol: "openai_image_generations",
|
||||
providerBaseUrl: "https://media.example/v1",
|
||||
providerName: "Unicode Media Provider",
|
||||
providerSelector: "unicode-media::openai_image_generations"
|
||||
}, { baseUrl: baseUrl(server) });
|
||||
|
||||
await executor.imageGenerate({ prompt: "A blue cup" }, {
|
||||
job: { id: "unicode-model-header-test" },
|
||||
onRemoteRequestId() {},
|
||||
signal: new AbortController().signal
|
||||
});
|
||||
|
||||
assert.equal(targetModelHeader, "image-model");
|
||||
assert.equal(requestBody.model, rawModel);
|
||||
});
|
||||
|
||||
test("implicit media input roots reject the filesystem root and home directory", () => {
|
||||
const home = path.resolve(os.homedir());
|
||||
assert.equal(mediaServiceForTest.isSafeImplicitWorkingDirectory(path.parse(home).root, home), false);
|
||||
|
||||
Reference in New Issue
Block a user