mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
fix(api): fixed POST request for API blocks (#392)
This commit is contained in:
@@ -71,28 +71,43 @@ export async function GET(request: Request) {
|
||||
return createErrorResponse("Missing 'url' parameter", 400)
|
||||
}
|
||||
|
||||
// Extract custom headers from the request
|
||||
const method = url.searchParams.get('method') || 'GET'
|
||||
|
||||
const bodyParam = url.searchParams.get('body')
|
||||
let body: string | undefined = undefined
|
||||
|
||||
if (bodyParam && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
|
||||
try {
|
||||
body = decodeURIComponent(bodyParam)
|
||||
} catch (error) {
|
||||
logger.warn(`[${requestId}] Failed to decode body parameter`, error)
|
||||
}
|
||||
}
|
||||
|
||||
const customHeaders: Record<string, string> = {}
|
||||
|
||||
// Process all header.* parameters in the URL
|
||||
for (const [key, value] of url.searchParams.entries()) {
|
||||
if (key.startsWith('header.')) {
|
||||
const headerName = key.substring(7) // Remove 'header.' prefix
|
||||
const headerName = key.substring(7)
|
||||
customHeaders[headerName] = value
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`[${requestId}] Proxying GET request to: ${targetUrl}`)
|
||||
logger.debug(`[${requestId}] Custom headers:`, customHeaders)
|
||||
if (body && !customHeaders['Content-Type']) {
|
||||
customHeaders['Content-Type'] = 'application/json'
|
||||
}
|
||||
|
||||
logger.info(`[${requestId}] Proxying ${method} request to: ${targetUrl}`)
|
||||
|
||||
try {
|
||||
// Forward the request to the target URL with all specified headers
|
||||
const response = await fetch(targetUrl, {
|
||||
method: 'GET',
|
||||
method: method,
|
||||
headers: {
|
||||
...getProxyHeaders(),
|
||||
...customHeaders,
|
||||
},
|
||||
body: body || undefined,
|
||||
})
|
||||
|
||||
// Get response data
|
||||
|
||||
@@ -452,5 +452,75 @@ describe('HTTP Request Tool', () => {
|
||||
// Reset window
|
||||
global.window = originalWindow
|
||||
})
|
||||
|
||||
test('should include method parameter in proxy URL', () => {
|
||||
const originalWindow = global.window
|
||||
Object.defineProperty(global, 'window', {
|
||||
value: {
|
||||
location: {
|
||||
origin: 'https://simstudio.ai',
|
||||
},
|
||||
},
|
||||
writable: true,
|
||||
})
|
||||
|
||||
const originalVitest = process.env.VITEST
|
||||
|
||||
try {
|
||||
process.env.VITEST = undefined
|
||||
|
||||
const buildProxyUrl = (params: any) => {
|
||||
const baseUrl = `https://external-api.com/endpoint`
|
||||
let proxyUrl = `/api/proxy?url=${encodeURIComponent(baseUrl)}`
|
||||
|
||||
if (params.method) {
|
||||
proxyUrl += `&method=${encodeURIComponent(params.method)}`
|
||||
}
|
||||
|
||||
if (
|
||||
params.body &&
|
||||
['POST', 'PUT', 'PATCH'].includes(params.method?.toUpperCase() || '')
|
||||
) {
|
||||
const bodyStr =
|
||||
typeof params.body === 'string' ? params.body : JSON.stringify(params.body)
|
||||
proxyUrl += `&body=${encodeURIComponent(bodyStr)}`
|
||||
}
|
||||
|
||||
return proxyUrl
|
||||
}
|
||||
|
||||
const getParams = {
|
||||
url: 'https://external-api.com/endpoint',
|
||||
method: 'GET',
|
||||
}
|
||||
const getProxyUrl = buildProxyUrl(getParams)
|
||||
expect(getProxyUrl).toContain('/api/proxy?url=')
|
||||
expect(getProxyUrl).toContain('&method=GET')
|
||||
|
||||
const postParams = {
|
||||
url: 'https://external-api.com/endpoint',
|
||||
method: 'POST',
|
||||
body: { key: 'value' },
|
||||
}
|
||||
const postProxyUrl = buildProxyUrl(postParams)
|
||||
expect(postProxyUrl).toContain('/api/proxy?url=')
|
||||
expect(postProxyUrl).toContain('&method=POST')
|
||||
expect(postProxyUrl).toContain('&body=')
|
||||
expect(postProxyUrl).toContain(encodeURIComponent('{"key":"value"}'))
|
||||
|
||||
const putParams = {
|
||||
url: 'https://external-api.com/endpoint',
|
||||
method: 'PUT',
|
||||
body: 'string body',
|
||||
}
|
||||
const putProxyUrl = buildProxyUrl(putParams)
|
||||
expect(putProxyUrl).toContain('/api/proxy?url=')
|
||||
expect(putProxyUrl).toContain('&method=PUT')
|
||||
expect(putProxyUrl).toContain(`&body=${encodeURIComponent('string body')}`)
|
||||
} finally {
|
||||
global.window = originalWindow
|
||||
process.env.VITEST = originalVitest
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -232,9 +232,18 @@ export const requestTool: ToolConfig<RequestParams, RequestResponse> = {
|
||||
|
||||
// Determine if we should use the proxy
|
||||
if (shouldUseProxy(url)) {
|
||||
// Route request through our proxy
|
||||
let proxyUrl = `/api/proxy?url=${encodeURIComponent(url)}`
|
||||
|
||||
if (params.method) {
|
||||
proxyUrl += `&method=${encodeURIComponent(params.method)}`
|
||||
}
|
||||
|
||||
if (params.body && ['POST', 'PUT', 'PATCH'].includes(params.method?.toUpperCase() || '')) {
|
||||
const bodyStr =
|
||||
typeof params.body === 'string' ? params.body : JSON.stringify(params.body)
|
||||
proxyUrl += `&body=${encodeURIComponent(bodyStr)}`
|
||||
}
|
||||
|
||||
// Forward all headers as URL parameters
|
||||
const userHeaders = transformTable(params.headers || null)
|
||||
|
||||
@@ -387,6 +396,16 @@ export const requestTool: ToolConfig<RequestParams, RequestResponse> = {
|
||||
if (shouldUseProxy(processedUrl)) {
|
||||
let proxyUrl = `/api/proxy?url=${encodeURIComponent(processedUrl)}`
|
||||
|
||||
if (params.method) {
|
||||
proxyUrl += `&method=${encodeURIComponent(params.method)}`
|
||||
}
|
||||
|
||||
if (params.body && ['POST', 'PUT', 'PATCH'].includes(params.method?.toUpperCase() || '')) {
|
||||
const bodyStr =
|
||||
typeof params.body === 'string' ? params.body : JSON.stringify(params.body)
|
||||
proxyUrl += `&body=${encodeURIComponent(bodyStr)}`
|
||||
}
|
||||
|
||||
// Forward all headers as URL parameters
|
||||
const userHeaders = transformTable(params.headers || null)
|
||||
for (const [key, value] of Object.entries(userHeaders)) {
|
||||
|
||||
Reference in New Issue
Block a user