Skip to content

Commit 09cfa0e

Browse files
committed
fix: check strict mode before proxy attempt
In --proxy-only mode the strict-mode 503 was unreachable because proxyAndRecord() returned early on success. Move the strict check before the proxy attempt in all 17 handlers so X-AIMock-Strict: true correctly prevents proxying and returns 503.
1 parent 71b1c95 commit 09cfa0e

17 files changed

Lines changed: 652 additions & 238 deletions

src/bedrock-converse.ts

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,34 @@ export async function handleConverse(
600600
return;
601601

602602
if (!fixture) {
603+
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
604+
if (effectiveStrict) {
605+
const strictStatus = 503;
606+
const strictMessage = "Strict mode: no fixture matched";
607+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
608+
journal.add({
609+
method: req.method ?? "POST",
610+
path: urlPath,
611+
headers: flattenHeaders(req.headers),
612+
body: completionReq,
613+
response: {
614+
status: strictStatus,
615+
fixture: null,
616+
...strictOverrideField(defaults.strict, req.headers),
617+
},
618+
});
619+
writeErrorResponse(
620+
res,
621+
strictStatus,
622+
JSON.stringify({
623+
error: {
624+
message: strictMessage,
625+
type: "invalid_request_error",
626+
},
627+
}),
628+
);
629+
return;
630+
}
603631
if (defaults.record) {
604632
const outcome = await proxyAndRecord(
605633
req,
@@ -623,31 +651,23 @@ export async function handleConverse(
623651
return;
624652
}
625653
}
626-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
627-
const strictStatus = effectiveStrict ? 503 : 404;
628-
const strictMessage = effectiveStrict
629-
? "Strict mode: no fixture matched"
630-
: "No fixture matched";
631-
if (effectiveStrict) {
632-
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
633-
}
634654
journal.add({
635655
method: req.method ?? "POST",
636656
path: urlPath,
637657
headers: flattenHeaders(req.headers),
638658
body: completionReq,
639659
response: {
640-
status: strictStatus,
660+
status: 404,
641661
fixture: null,
642662
...strictOverrideField(defaults.strict, req.headers),
643663
},
644664
});
645665
writeErrorResponse(
646666
res,
647-
strictStatus,
667+
404,
648668
JSON.stringify({
649669
error: {
650-
message: strictMessage,
670+
message: "No fixture matched",
651671
type: "invalid_request_error",
652672
},
653673
}),
@@ -871,6 +891,34 @@ export async function handleConverseStream(
871891
return;
872892

873893
if (!fixture) {
894+
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
895+
if (effectiveStrict) {
896+
const strictStatus = 503;
897+
const strictMessage = "Strict mode: no fixture matched";
898+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
899+
journal.add({
900+
method: req.method ?? "POST",
901+
path: urlPath,
902+
headers: flattenHeaders(req.headers),
903+
body: completionReq,
904+
response: {
905+
status: strictStatus,
906+
fixture: null,
907+
...strictOverrideField(defaults.strict, req.headers),
908+
},
909+
});
910+
writeErrorResponse(
911+
res,
912+
strictStatus,
913+
JSON.stringify({
914+
error: {
915+
message: strictMessage,
916+
type: "invalid_request_error",
917+
},
918+
}),
919+
);
920+
return;
921+
}
874922
if (defaults.record) {
875923
const outcome = await proxyAndRecord(
876924
req,
@@ -894,31 +942,23 @@ export async function handleConverseStream(
894942
return;
895943
}
896944
}
897-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
898-
const strictStatus = effectiveStrict ? 503 : 404;
899-
const strictMessage = effectiveStrict
900-
? "Strict mode: no fixture matched"
901-
: "No fixture matched";
902-
if (effectiveStrict) {
903-
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
904-
}
905945
journal.add({
906946
method: req.method ?? "POST",
907947
path: urlPath,
908948
headers: flattenHeaders(req.headers),
909949
body: completionReq,
910950
response: {
911-
status: strictStatus,
951+
status: 404,
912952
fixture: null,
913953
...strictOverrideField(defaults.strict, req.headers),
914954
},
915955
});
916956
writeErrorResponse(
917957
res,
918-
strictStatus,
958+
404,
919959
JSON.stringify({
920960
error: {
921-
message: strictMessage,
961+
message: "No fixture matched",
922962
type: "invalid_request_error",
923963
},
924964
}),

src/bedrock.ts

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,34 @@ export async function handleBedrock(
428428
return;
429429

430430
if (!fixture) {
431+
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
432+
if (effectiveStrict) {
433+
const strictStatus = 503;
434+
const strictMessage = "Strict mode: no fixture matched";
435+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
436+
journal.add({
437+
method: req.method ?? "POST",
438+
path: urlPath,
439+
headers: flattenHeaders(req.headers),
440+
body: completionReq,
441+
response: {
442+
status: strictStatus,
443+
fixture: null,
444+
...strictOverrideField(defaults.strict, req.headers),
445+
},
446+
});
447+
writeErrorResponse(
448+
res,
449+
strictStatus,
450+
JSON.stringify({
451+
error: {
452+
message: strictMessage,
453+
type: "invalid_request_error",
454+
},
455+
}),
456+
);
457+
return;
458+
}
431459
if (defaults.record) {
432460
const outcome = await proxyAndRecord(
433461
req,
@@ -451,31 +479,23 @@ export async function handleBedrock(
451479
return;
452480
}
453481
}
454-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
455-
const strictStatus = effectiveStrict ? 503 : 404;
456-
const strictMessage = effectiveStrict
457-
? "Strict mode: no fixture matched"
458-
: "No fixture matched";
459-
if (effectiveStrict) {
460-
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
461-
}
462482
journal.add({
463483
method: req.method ?? "POST",
464484
path: urlPath,
465485
headers: flattenHeaders(req.headers),
466486
body: completionReq,
467487
response: {
468-
status: strictStatus,
488+
status: 404,
469489
fixture: null,
470490
...strictOverrideField(defaults.strict, req.headers),
471491
},
472492
});
473493
writeErrorResponse(
474494
res,
475-
strictStatus,
495+
404,
476496
JSON.stringify({
477497
error: {
478-
message: strictMessage,
498+
message: "No fixture matched",
479499
type: "invalid_request_error",
480500
},
481501
}),
@@ -1049,6 +1069,34 @@ export async function handleBedrockStream(
10491069
return;
10501070

10511071
if (!fixture) {
1072+
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
1073+
if (effectiveStrict) {
1074+
const strictStatus = 503;
1075+
const strictMessage = "Strict mode: no fixture matched";
1076+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
1077+
journal.add({
1078+
method: req.method ?? "POST",
1079+
path: urlPath,
1080+
headers: flattenHeaders(req.headers),
1081+
body: completionReq,
1082+
response: {
1083+
status: strictStatus,
1084+
fixture: null,
1085+
...strictOverrideField(defaults.strict, req.headers),
1086+
},
1087+
});
1088+
writeErrorResponse(
1089+
res,
1090+
strictStatus,
1091+
JSON.stringify({
1092+
error: {
1093+
message: strictMessage,
1094+
type: "invalid_request_error",
1095+
},
1096+
}),
1097+
);
1098+
return;
1099+
}
10521100
if (defaults.record) {
10531101
const outcome = await proxyAndRecord(
10541102
req,
@@ -1072,31 +1120,23 @@ export async function handleBedrockStream(
10721120
return;
10731121
}
10741122
}
1075-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
1076-
const strictStatus = effectiveStrict ? 503 : 404;
1077-
const strictMessage = effectiveStrict
1078-
? "Strict mode: no fixture matched"
1079-
: "No fixture matched";
1080-
if (effectiveStrict) {
1081-
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
1082-
}
10831123
journal.add({
10841124
method: req.method ?? "POST",
10851125
path: urlPath,
10861126
headers: flattenHeaders(req.headers),
10871127
body: completionReq,
10881128
response: {
1089-
status: strictStatus,
1129+
status: 404,
10901130
fixture: null,
10911131
...strictOverrideField(defaults.strict, req.headers),
10921132
},
10931133
});
10941134
writeErrorResponse(
10951135
res,
1096-
strictStatus,
1136+
404,
10971137
JSON.stringify({
10981138
error: {
1099-
message: strictMessage,
1139+
message: "No fixture matched",
11001140
type: "invalid_request_error",
11011141
},
11021142
}),

src/cohere.ts

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,36 @@ export async function handleCohere(
864864
return;
865865

866866
if (!fixture) {
867+
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
868+
if (effectiveStrict) {
869+
const strictStatus = 503;
870+
const strictMessage = "Strict mode: no fixture matched";
871+
logger.error(
872+
`STRICT: No fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v2/chat"}`,
873+
);
874+
journal.add({
875+
method: req.method ?? "POST",
876+
path: req.url ?? "/v2/chat",
877+
headers: flattenHeaders(req.headers),
878+
body: completionReq,
879+
response: {
880+
status: strictStatus,
881+
fixture: null,
882+
...strictOverrideField(defaults.strict, req.headers),
883+
},
884+
});
885+
writeErrorResponse(
886+
res,
887+
strictStatus,
888+
JSON.stringify({
889+
error: {
890+
message: strictMessage,
891+
type: "invalid_request_error",
892+
},
893+
}),
894+
);
895+
return;
896+
}
867897
if (defaults.record) {
868898
const outcome = await proxyAndRecord(
869899
req,
@@ -887,33 +917,23 @@ export async function handleCohere(
887917
return;
888918
}
889919
}
890-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
891-
const strictStatus = effectiveStrict ? 503 : 404;
892-
const strictMessage = effectiveStrict
893-
? "Strict mode: no fixture matched"
894-
: "No fixture matched";
895-
if (effectiveStrict) {
896-
logger.error(
897-
`STRICT: No fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v2/chat"}`,
898-
);
899-
}
900920
journal.add({
901921
method: req.method ?? "POST",
902922
path: req.url ?? "/v2/chat",
903923
headers: flattenHeaders(req.headers),
904924
body: completionReq,
905925
response: {
906-
status: strictStatus,
926+
status: 404,
907927
fixture: null,
908928
...strictOverrideField(defaults.strict, req.headers),
909929
},
910930
});
911931
writeErrorResponse(
912932
res,
913-
strictStatus,
933+
404,
914934
JSON.stringify({
915935
error: {
916-
message: strictMessage,
936+
message: "No fixture matched",
917937
type: "invalid_request_error",
918938
},
919939
}),

0 commit comments

Comments
 (0)