- {contentType === "application/json" ? (
+ {bodyType === "json" ? (
// wrap with div to position error tooltip
bodyRef.current?.checkValidity()}
/>
@@ -689,7 +765,7 @@ const BodyField = ({
color={bodyError ? "error" : undefined}
value={String(evaluateExpressionWithinScope(value, scope) ?? "")}
// update text value as string literal
- onChange={(newValue) => onChange(JSON.stringify(newValue))}
+ onChange={(newValue) => updateBody(JSON.stringify(newValue))}
onBlur={() => bodyRef.current?.checkValidity()}
/>
)}
@@ -700,11 +776,11 @@ const BodyField = ({
variant={isBodyLiteral ? "default" : "bound"}
value={value}
onChange={(value) => {
- onChange(value);
+ updateBody(value);
setIsBodyLiteral(isLiteralExpression(value));
}}
onRemove={(evaluatedValue) => {
- onChange(JSON.stringify(evaluatedValue));
+ updateBody(JSON.stringify(evaluatedValue));
setIsBodyLiteral(true);
}}
/>
@@ -713,8 +789,39 @@ const BodyField = ({
);
};
-const isContentTypeHeader = (header: Resource["headers"][number]) =>
- header.name.toLowerCase() === "content-type";
+const isCacheControl = (name: string) => name.toLowerCase() === "cache-control";
+const isContentType = (name: string) => name.toLowerCase() === "content-type";
+
+const parseHeaders = (headers: Resource["headers"]) => {
+ let maxAge: undefined | string;
+ let bodyType: BodyType;
+ const newHeaders = headers.filter((header) => {
+ const value = computeExpression(header.value, new Map()).toLowerCase();
+ if (isCacheControl(header.name)) {
+ // move simple header like Cache-Control: max-age=10 to dedicated input
+ // preserve more complex cache-control
+ const matched = value.match(/^max-age=(\d+)$/);
+ if (matched) {
+ [, maxAge] = matched;
+ return false;
+ }
+ }
+ // store json and text in dedicated input
+ // and preserve other types
+ if (isContentType(header.name)) {
+ if (value === "application/json") {
+ bodyType = "json";
+ return false;
+ }
+ if (value === "text/plain") {
+ bodyType = "text";
+ return false;
+ }
+ }
+ return false;
+ });
+ return { headers: newHeaders, maxAge, bodyType };
+};
export const ResourceForm = forwardRef<
undefined | PanelApi,
@@ -727,6 +834,7 @@ export const ResourceForm = forwardRef<
variable?.type === "resource"
? resources.get(variable.resourceId)
: undefined;
+ const parsedHeaders = parseHeaders(resource?.headers ?? []);
const [url, setUrl] = useState(resource?.url ?? `""`);
const [method, setMethod] = useState(
@@ -736,14 +844,11 @@ export const ResourceForm = forwardRef<
resource?.searchParams ?? []
);
const [headers, setHeaders] = useState(
- resource?.headers ?? []
+ parsedHeaders.headers
);
- const [body, setBody] = useState(() => resource?.body);
-
- const contentType = headers.find(isContentTypeHeader)?.value;
- const evaluatedContentType = contentType
- ? evaluateExpressionWithinScope(contentType, scope)
- : undefined;
+ const [maxAge, setMaxAge] = useState(parsedHeaders.maxAge);
+ const [bodyType, setBodyType] = useState(parsedHeaders.bodyType);
+ const [body, setBody] = useState(resource?.body);
useImperativeHandle(ref, () => ({
save: (formData) => {
@@ -798,12 +903,15 @@ export const ResourceForm = forwardRef<
value: JSON.stringify(header.value),
}))
);
- setHeaders(
+ const parsedHeaders = parseHeaders(
curl.headers.map((header) => ({
name: header.name,
value: JSON.stringify(header.value),
}))
);
+ setMaxAge(parsedHeaders.maxAge);
+ setHeaders(parsedHeaders.headers);
+ setBodyType(parsedHeaders.bodyType);
setBody(JSON.stringify(curl.body));
}}
/>
@@ -813,38 +921,44 @@ export const ResourceForm = forwardRef<
searchParams={searchParams}
onChange={setSearchParams}
/>
+ {
+ setMaxAge(newMaxAge);
+ // reset header
+ setHeaders((headers) =>
+ headers.filter(({ name }) => !isCacheControl(name))
+ );
+ }}
+ />
{
+ // reset dedicated fields
+ if (newHeaders.some(({ name }) => isCacheControl(name))) {
+ setMaxAge(undefined);
+ }
+ if (newHeaders.some(({ name }) => isContentType(name))) {
+ setBodyType(undefined);
+ }
+ setHeaders(newHeaders);
+ }}
/>
{method !== "get" && (
{
- const evaluatedValue = evaluateExpressionWithinScope(
- newBody,
- scope
- );
- // automatically add Content-Type: application/json header
- // when value is object
- if (
- typeof evaluatedValue === "object" &&
- evaluatedValue !== null &&
- evaluatedContentType !== "application/json"
- ) {
- setHeaders((prevHeaders) => {
- const newHeaders = prevHeaders.filter(isContentTypeHeader);
- newHeaders.push({
- name: "Content-Type",
- value: JSON.stringify("application/json"),
- });
- return newHeaders;
- });
+ bodyType={bodyType}
+ onChange={(newBody, newBodyType) => {
+ setBodyType(newBodyType);
+ // reset header
+ if (newBodyType) {
+ setHeaders((headers) =>
+ headers.filter(({ name }) => !isContentType(name))
+ );
}
setBody(newBody);
}}
@@ -963,11 +1077,9 @@ export const GraphqlResourceForm = forwardRef<
: undefined;
const [url, setUrl] = useState(resource?.url ?? `""`);
- const [headers, setHeaders] = useState(
- resource?.headers ?? [
- { name: "Content-Type", value: JSON.stringify("application/json") },
- ]
- );
+ const parsedHeaders = parseHeaders(resource?.headers ?? []);
+ const [maxAge, setMaxAge] = useState(parsedHeaders.maxAge);
+ const [headers, setHeaders] = useState(parsedHeaders.headers);
const [bodyExpressions] = useState(() =>
parseObjectExpression(resource?.body ?? "")
@@ -1017,7 +1129,10 @@ export const GraphqlResourceForm = forwardRef<
control: "graphql",
url,
method: "post",
- headers,
+ headers: [
+ ...headers,
+ { name: "Content-Type", value: "application/json" },
+ ],
body,
};
const newVariable: DataSource = {
@@ -1048,12 +1163,14 @@ export const GraphqlResourceForm = forwardRef<
onCurlPaste={(curl) => {
// update all feilds when curl is paste into url field
setUrl(JSON.stringify(curl.url));
- setHeaders(
+ const parsedHeaders = parseHeaders(
curl.headers.map((header) => ({
name: header.name,
value: JSON.stringify(header.value),
}))
);
+ setMaxAge(parsedHeaders.maxAge);
+ setHeaders(parsedHeaders.headers);
const body = zGraphqlBody.safeParse(curl.body);
if (body.success) {
setQuery(body.data.query);
@@ -1139,11 +1256,27 @@ export const GraphqlResourceForm = forwardRef<