TASK22102: slice3 migrate file proxy handlers

This commit is contained in:
2026-03-17 12:58:20 +00:00
parent f16161bcee
commit 3cbd876b77
5 changed files with 80 additions and 12 deletions
+32
View File
@@ -1371,3 +1371,35 @@ Validation:
Follow-ups: Follow-ups:
- Next slice can target selected file handlers for equivalent response contract cleanup. - Next slice can target selected file handlers for equivalent response contract cleanup.
---
### CL-037: TASK22102 API contract consistency — Slice 3 (file proxy handlers)
date: 2026-03-17
author: Cline
scope: `pages/api/file/{getbloblistproxy,getrepsblobproxy,getawaitingsubmissionfromblobproxy,createappealcompletemessageproxy_api}.js`
type: change
rationale: Extend contract consistency into selected proxy file handlers by replacing raw error passthrough and empty 400s with standardized structured responses.
impact: Improves API error contract clarity for selected file proxy routes while preserving success payload pass-through behavior.
status: completed
Summary:
- Migrated selected file proxy handlers to shared response helper usage:
- `getbloblistproxy`
- `getrepsblobproxy`
- `getawaitingsubmissionfromblobproxy`
- `createappealcompletemessageproxy_api`
- Replaced direct `res.status(...).json(...)` handling with:
- `respondSuccess(...)`
- `respondError(...)`
- Added explicit structured 400 responses for missing required query values and proxy fetch failures.
Validation:
- `npx next lint --file pages/api/file/getbloblistproxy.js --file pages/api/file/getrepsblobproxy.js --file pages/api/file/getawaitingsubmissionfromblobproxy.js --file pages/api/file/createappealcompletemessageproxy_api.js` -> pass (no warnings/errors)
Follow-ups:
- Next slice should target non-proxy file handlers that still return raw `error` payloads.
@@ -3,6 +3,7 @@ import { getToken } from "../../../actions/core/token";
import { azureHeaders } from "../../../actions/core/headers"; import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger"; import { consoleLogger } from "../../../actions/core/logger";
import axios from "axios"; import axios from "axios";
import { respondError, respondSuccess } from "../middleware/apiResponse";
import nextConnect from "next-connect"; import nextConnect from "next-connect";
import middleware from "../middleware/middleware"; import middleware from "../middleware/middleware";
@@ -20,7 +21,11 @@ ApiProxy.get(async (req, res) => {
var tempCaseRef = req.query.tempcaseref; var tempCaseRef = req.query.tempcaseref;
if (!hasValue(containerName) || !hasValue(tempCaseRef)) { if (!hasValue(containerName) || !hasValue(tempCaseRef)) {
return res.status(400).json(); return respondError(res, {
status: 400,
code: "MISSING_REQUIRED_QUERY",
message: "container and tempcaseref are required"
});
} }
var token = await getToken(); var token = await getToken();
@@ -37,11 +42,15 @@ ApiProxy.get(async (req, res) => {
azureHeaders(token.access_token) azureHeaders(token.access_token)
) )
.then(({ data }) => { .then(({ data }) => {
res.status(200).json(data); return respondSuccess(res, data);
}) })
.catch((error) => { .catch((error) => {
consoleLogger(error); consoleLogger(error);
res.status(400).json(error); return respondError(res, {
status: 400,
code: "CREATE_APPEAL_COMPLETE_MESSAGE_PROXY_FAILED",
message: "Failed to create appeal complete message"
});
}); });
}); });
@@ -3,6 +3,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger"; import { consoleLogger } from "../../../actions/core/logger";
import { hashAPIPath } from "../../../actions/core/hash"; import { hashAPIPath } from "../../../actions/core/hash";
import axios from "axios"; import axios from "axios";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`; const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`;
@@ -13,7 +14,11 @@ export default async function ApiProxy(req, res) {
var containerName = req.query.container; var containerName = req.query.container;
if (!hasValue(containerName)) { if (!hasValue(containerName)) {
return res.status(400).json(); return respondError(res, {
status: 400,
code: "MISSING_REQUIRED_QUERY",
message: "container is required"
});
} }
var token = await getToken(); var token = await getToken();
@@ -27,10 +32,14 @@ export default async function ApiProxy(req, res) {
azureHeaders(token.access_token) azureHeaders(token.access_token)
) )
.then(({ data }) => { .then(({ data }) => {
res.status(200).json(data); return respondSuccess(res, data);
}) })
.catch((error) => { .catch((error) => {
consoleLogger(error); consoleLogger(error);
res.status(400).json(error); return respondError(res, {
status: 400,
code: "GET_AWAITING_SUBMISSION_PROXY_FAILED",
message: "Failed to fetch awaiting submission blob"
});
}); });
} }
+12 -3
View File
@@ -3,6 +3,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger"; import { consoleLogger } from "../../../actions/core/logger";
import { hashAPIPath } from "../../../actions/core/hash"; import { hashAPIPath } from "../../../actions/core/hash";
import axios from "axios"; import axios from "axios";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`; const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`;
@@ -14,7 +15,11 @@ export default async function ApiProxy(req, res) {
var casefolderID = req.query.casefolderID; var casefolderID = req.query.casefolderID;
if (!hasValue(containerName) || !hasValue(casefolderID)) { if (!hasValue(containerName) || !hasValue(casefolderID)) {
return res.status(400).json(); return respondError(res, {
status: 400,
code: "MISSING_REQUIRED_QUERY",
message: "container and casefolderID are required"
});
} }
var token = await getToken(); var token = await getToken();
@@ -31,10 +36,14 @@ export default async function ApiProxy(req, res) {
azureHeaders(token.access_token) azureHeaders(token.access_token)
) )
.then(({ data }) => { .then(({ data }) => {
res.status(200).json(data); return respondSuccess(res, data);
}) })
.catch((error) => { .catch((error) => {
consoleLogger(error); consoleLogger(error);
res.status(400).json(error); return respondError(res, {
status: 400,
code: "GET_BLOB_LIST_PROXY_FAILED",
message: "Failed to fetch blob list"
});
}); });
} }
+12 -3
View File
@@ -3,6 +3,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger"; import { consoleLogger } from "../../../actions/core/logger";
import { hashAPIPath } from "../../../actions/core/hash"; import { hashAPIPath } from "../../../actions/core/hash";
import axios from "axios"; import axios from "axios";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`; const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`;
@@ -13,7 +14,11 @@ export default async function ApiProxy(req, res) {
var containerName = req.query.container; var containerName = req.query.container;
if (!hasValue(containerName)) { if (!hasValue(containerName)) {
return res.status(400).json(); return respondError(res, {
status: 400,
code: "MISSING_REQUIRED_QUERY",
message: "container is required"
});
} }
var token = await getToken(); var token = await getToken();
@@ -26,10 +31,14 @@ export default async function ApiProxy(req, res) {
azureHeaders(token.access_token) azureHeaders(token.access_token)
) )
.then(({ data }) => { .then(({ data }) => {
res.status(200).json(data); return respondSuccess(res, data);
}) })
.catch((error) => { .catch((error) => {
consoleLogger(error); consoleLogger(error);
res.status(400).json(error); return respondError(res, {
status: 400,
code: "GET_REPS_BLOB_PROXY_FAILED",
message: "Failed to fetch representation blobs"
});
}); });
} }