Skip to content

Commit a202648

Browse files
authored
fix: show resource validation error as response (#5402)
Sometimes users are able to save broken resource for example without header value. We need to prevent failing all requests and instead fail only broken one.
1 parent 05d8baf commit a202648

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

apps/builder/app/routes/rest.resources-loader.ts

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,35 @@ export const action = async ({ request }: ActionFunctionArgs) => {
2525
};
2626

2727
const requestJson = await request.json();
28+
const requestList = z.array(z.unknown()).safeParse(requestJson);
2829

29-
const computedResourcesParsed = z
30-
.array(ResourceRequest)
31-
.safeParse(requestJson);
32-
33-
if (computedResourcesParsed.success === false) {
34-
console.error(
35-
"computedResources.parse",
36-
computedResourcesParsed.error.toString()
37-
);
30+
if (requestList.success === false) {
3831
console.error("data:", requestJson);
39-
40-
throw data(computedResourcesParsed.error, {
32+
throw data(requestList.error, {
4133
status: 400,
4234
});
4335
}
4436

45-
const computedResources = computedResourcesParsed.data;
46-
47-
const responses = await Promise.all(
48-
computedResources.map((resource) => loadResource(customFetch, resource))
37+
const output = await Promise.all(
38+
requestList.data.map(async (item) => {
39+
const resource = ResourceRequest.safeParse(item);
40+
if (resource.success === false) {
41+
return [
42+
getResourceKey(item as ResourceRequest),
43+
{
44+
ok: false,
45+
data: resource.error.format(),
46+
status: 403,
47+
statusText: "Resource validation error",
48+
},
49+
];
50+
}
51+
return [
52+
getResourceKey(resource.data),
53+
await loadResource(customFetch, resource.data),
54+
];
55+
})
4956
);
50-
const output: [string, unknown][] = [];
51-
responses.forEach((response, index) => {
52-
const request = computedResources[index];
53-
output.push([getResourceKey(request), response]);
54-
});
57+
5558
return output;
5659
};

apps/builder/app/shared/resources.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,24 @@ import { fetch } from "./fetch.client";
77

88
const MAX_PENDING_RESOURCES = 5;
99

10-
export const getResourceKey = (resource: ResourceRequest) =>
11-
hash(
12-
JSON.stringify([
13-
// explicitly list all fields to keep hash stable
14-
resource.name,
15-
resource.method,
16-
resource.url,
17-
resource.searchParams,
18-
resource.headers,
19-
resource.body,
20-
])
21-
);
10+
export const getResourceKey = (resource: ResourceRequest) => {
11+
try {
12+
return hash(
13+
JSON.stringify([
14+
// explicitly list all fields to keep hash stable
15+
resource.name,
16+
resource.method,
17+
resource.url,
18+
resource.searchParams,
19+
resource.headers,
20+
resource.body,
21+
])
22+
);
23+
} catch {
24+
// guard from invalid resources
25+
return "";
26+
}
27+
};
2228

2329
const queue = new Map<string, ResourceRequest>();
2430
const pending = new Map<string, ResourceRequest>();

0 commit comments

Comments
 (0)