Skip to content

Commit ea1ddc3

Browse files
authored
[Docs Site] Support parameter substitution in APIRequest (#20501)
1 parent a13d76d commit ea1ddc3

File tree

2 files changed

+55
-13
lines changed

2 files changed

+55
-13
lines changed

src/components/APIRequest.astro

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import Details from "./Details.astro";
88
99
type Props = z.input<typeof props>;
1010
11-
const props = z.object({
12-
path: z.string(),
13-
method: z.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]),
14-
json: z.record(z.string(), z.any()).default({}),
15-
});
11+
const props = z
12+
.object({
13+
path: z.string(),
14+
method: z.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]),
15+
parameters: z.record(z.string(), z.any()).optional(),
16+
json: z.record(z.string(), z.any()).optional(),
17+
})
18+
.strict();
1619
17-
const { path, method, json } = props.parse(Astro.props);
20+
let { path, method, parameters, json } = props.parse(Astro.props);
1821
1922
const schema = await getSchema();
2023
@@ -36,13 +39,40 @@ if (!operation) {
3639
const url = new URL(path, "https://api.cloudflare.com/client/v4");
3740
const headers: Record<string, string> = {};
3841
42+
const providedParameters = Object.keys(parameters ?? {});
43+
const endpointParameters = (operation.parameters ??
44+
[]) as OpenAPIV3.ParameterObject[];
45+
46+
const extraneousParameters = providedParameters.filter(
47+
(parameter) =>
48+
!endpointParameters.some(
49+
(endpointParam) => endpointParam.name === parameter,
50+
),
51+
);
52+
53+
if (extraneousParameters.length > 0) {
54+
throw new Error(
55+
`[APIRequest] Provided parameters ${extraneousParameters.join(", ")} not found in schema.`,
56+
);
57+
}
58+
59+
for (const parameter of endpointParameters) {
60+
if (parameter.in === "path") {
61+
const encoded = encodeURIComponent(`{${parameter.name}}`);
62+
63+
if (parameters?.[parameter.name]) {
64+
url.pathname = url.pathname.replace(encoded, parameters[parameter.name]);
65+
}
66+
}
67+
}
68+
3969
const segments = url.pathname.split("/").filter(Boolean);
70+
4071
for (const segment of segments) {
4172
const decoded = decodeURIComponent(segment);
4273
4374
if (decoded.startsWith("{") && decoded.endsWith("}")) {
4475
const placeholder = "$" + decoded.slice(1, -1).toUpperCase();
45-
4676
url.pathname = url.pathname.replace(segment, placeholder);
4777
}
4878
}
@@ -70,13 +100,9 @@ const jsonSchema = requestBody?.content?.["application/json"]?.schema as
70100
| OpenAPIV3.SchemaObject
71101
| undefined;
72102
73-
if (!jsonSchema) {
74-
throw new Error(
75-
`[APIRequest] This component currently does not support operations that do not accept JSON bodies.`,
76-
);
77-
}
103+
if (jsonSchema?.required) {
104+
json ??= {};
78105
79-
if (jsonSchema.required) {
80106
const providedProperties = Object.keys(json);
81107
const requiredProperties = jsonSchema.required;
82108

src/content/docs/style-guide/components/api-request.mdx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ import { APIRequest } from "~/components";
2020
validation_default_mitigation_action: "block"
2121
}}
2222
/>
23+
24+
<APIRequest
25+
path="/zones/{zone_id}/hostnames/settings/{setting_id}/{hostname}"
26+
method="DELETE"
27+
parameters={{
28+
setting_id: "ciphers",
29+
}}
30+
/>
2331
```
2432

2533
## `<APIRequest>` Props
@@ -42,6 +50,14 @@ This can be found in our [API documentation](https://api.cloudflare.com), under
4250

4351
The HTTP method to use.
4452

53+
### `parameters`
54+
55+
**type:** `Record<string, any>`
56+
57+
The path parameters to substitute.
58+
59+
If not provided, the component will default to an environment variable. For example, `{setting_id}` will be replaced with `$SETTING_ID`.
60+
4561
### `json`
4662

4763
**type:** `Record<string, any>`

0 commit comments

Comments
 (0)