fix(integration): escaping content for json body in custom integrations (#4728)
* fix: add jsonEscape option for placeholder replacement Enhance the replacePlaceholders method to support JSON escaping of values when specified in options. This improves handling of JSON strings in templates. * fix(integration): add default Content-Type header for non-GET methods
This commit is contained in:
parent
387a342665
commit
6d808df3e6
|
|
@ -116,6 +116,7 @@ export class CustomIntegrationManager {
|
|||
options: {
|
||||
urlEncode?: boolean
|
||||
htmlEscape?: boolean
|
||||
jsonEscape?: boolean
|
||||
} = {},
|
||||
): string {
|
||||
let result = template
|
||||
|
|
@ -149,6 +150,11 @@ export class CustomIntegrationManager {
|
|||
.replaceAll("'", "'")
|
||||
}
|
||||
|
||||
if (options.jsonEscape) {
|
||||
// Learn more https://stackoverflow.com/questions/4253367/how-to-escape-a-json-string-containing-newline-characters-using-javascript
|
||||
processedValue = JSON.stringify(processedValue).slice(1, -1)
|
||||
}
|
||||
|
||||
result = result.replaceAll(placeholder, processedValue)
|
||||
})
|
||||
|
||||
|
|
@ -175,13 +181,15 @@ export class CustomIntegrationManager {
|
|||
Object.entries(fetchTemplate.headers).forEach(([key, value]) => {
|
||||
const processedKey = this.replacePlaceholders(key, context)
|
||||
const processedValue = this.replacePlaceholders(value, context)
|
||||
processedHeaders[processedKey] = processedValue
|
||||
// Field names are case-insensitive.
|
||||
processedHeaders[processedKey.toLowerCase()] = processedValue
|
||||
})
|
||||
|
||||
// Process body without URL encoding
|
||||
let processedBody: string | undefined
|
||||
if (fetchTemplate.body) {
|
||||
processedBody = this.replacePlaceholders(fetchTemplate.body, context)
|
||||
const jsonEscape = fetchTemplate.headers["content-type"]?.toLowerCase() === "application/json"
|
||||
processedBody = this.replacePlaceholders(fetchTemplate.body, context, { jsonEscape })
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -325,6 +325,38 @@ export const CustomIntegrationModalContent = ({
|
|||
[form],
|
||||
)
|
||||
|
||||
const handleMethodChange = useCallback(
|
||||
(onChange: (value: string) => void) => (value: string) => {
|
||||
onChange(value)
|
||||
|
||||
const currentHeaders: Record<string, string> = form.getValues("fetchTemplate.headers") || {}
|
||||
|
||||
if (value !== "GET") {
|
||||
// Add default Content-Type header for non-GET methods
|
||||
const hasContentType = Object.keys(currentHeaders).some(
|
||||
(key) => key.toLowerCase() === "content-type",
|
||||
)
|
||||
|
||||
if (!hasContentType) {
|
||||
form.setValue("fetchTemplate.headers", {
|
||||
...currentHeaders,
|
||||
"Content-Type": "application/json",
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Remove Content-Type: application/json header for GET method
|
||||
const filteredHeaders: Record<string, string> = {}
|
||||
Object.entries(currentHeaders).forEach(([key, value]) => {
|
||||
if (key.toLowerCase() !== "content-type" || value.toLowerCase() !== "application/json") {
|
||||
filteredHeaders[key] = value
|
||||
}
|
||||
})
|
||||
form.setValue("fetchTemplate.headers", filteredHeaders)
|
||||
}
|
||||
},
|
||||
[form],
|
||||
)
|
||||
|
||||
// Memoized items
|
||||
const integrationTypeItems = useMemo(
|
||||
() => [
|
||||
|
|
@ -455,7 +487,7 @@ export const CustomIntegrationModalContent = ({
|
|||
<FormControl>
|
||||
<MethodSelector
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
onChange={handleMethodChange(field.onChange)}
|
||||
items={httpMethodItems}
|
||||
/>
|
||||
</FormControl>
|
||||
|
|
|
|||
Loading…
Reference in New Issue