test.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { IS_PLATFORM } from 'common'
  2. import { NextApiRequest, NextApiResponse } from 'next'
  3. import { isValidEdgeFunctionURL } from '@/lib/api/edgeFunctions'
  4. export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  5. const { method } = req
  6. switch (method) {
  7. case 'POST':
  8. return handlePost(req, res)
  9. default:
  10. return new Response(
  11. JSON.stringify({ data: null, error: { message: `Method ${method} Not Allowed` } }),
  12. {
  13. status: 405,
  14. headers: { 'Content-Type': 'application/json', Allow: 'POST' },
  15. }
  16. )
  17. }
  18. }
  19. async function handlePost(req: NextApiRequest, res: NextApiResponse) {
  20. try {
  21. const { url: requestUrl, method, body: requestBody, headers: customHeaders } = req.body
  22. const url = IS_PLATFORM
  23. ? requestUrl
  24. : requestUrl.replace(process.env.BRIVEN_PUBLIC_URL, process.env.BRIVEN_URL)
  25. const validEdgeFnUrl = isValidEdgeFunctionURL(url, IS_PLATFORM)
  26. if (!validEdgeFnUrl) {
  27. return res.status(400).json({
  28. status: 400,
  29. error: { message: 'Provided URL is not a valid Briven edge function URL' },
  30. })
  31. }
  32. // Remove any undefined or null values from custom headers
  33. const sanitizedCustomHeaders = Object.entries(customHeaders || {}).reduce(
  34. (acc, [key, value]) => {
  35. if (value !== undefined && value !== null && value !== '') {
  36. acc[key] = value as string
  37. }
  38. return acc
  39. },
  40. {} as Record<string, string>
  41. )
  42. // Only use custom headers and ensure Content-Type is set
  43. const requestHeaders: Record<string, string> = {
  44. 'Content-Type': 'application/json',
  45. ...sanitizedCustomHeaders,
  46. }
  47. // Use the test authorization header if provided
  48. if (sanitizedCustomHeaders['x-test-authorization']) {
  49. requestHeaders['Authorization'] = sanitizedCustomHeaders['x-test-authorization']
  50. // Remove the x-test-authorization header as we've moved it to Authorization
  51. delete requestHeaders['x-test-authorization']
  52. }
  53. // Prepare the request body based on method and Content-Type
  54. let finalBody = undefined
  55. if (method !== 'GET' && method !== 'HEAD') {
  56. if (requestHeaders['Content-Type'] === 'application/json') {
  57. finalBody = typeof requestBody === 'string' ? requestBody : JSON.stringify(requestBody)
  58. } else {
  59. finalBody = requestBody
  60. }
  61. }
  62. const response = await fetch(url, {
  63. method,
  64. headers: requestHeaders,
  65. body: finalBody,
  66. redirect: 'manual', // don't follow the redirect and return response as is
  67. })
  68. // Handle non-JSON responses
  69. let responseBody: string
  70. const contentType = response.headers.get('content-type')
  71. if (contentType?.includes('application/json')) {
  72. // If JSON, parse and stringify to ensure it's valid JSON
  73. const jsonBody = await response.json()
  74. responseBody = JSON.stringify(jsonBody)
  75. } else {
  76. // For non-JSON responses, get raw text
  77. responseBody = await response.text()
  78. }
  79. if (!response.ok) {
  80. // Try to parse error response if it's JSON
  81. try {
  82. const errorBody = JSON.parse(responseBody)
  83. return res.status(response.status).json({
  84. status: response.status,
  85. error: { message: errorBody?.error || 'Edge function returned an error' },
  86. })
  87. } catch (parseError) {
  88. // If not JSON, return the raw error
  89. return res.status(response.status).json({
  90. status: response.status,
  91. error: { message: responseBody || 'Edge function returned an error' },
  92. })
  93. }
  94. }
  95. const responseHeaders: Record<string, string> = {}
  96. response.headers.forEach((value, key) => {
  97. responseHeaders[key] = value
  98. })
  99. return res.status(response.status).json({
  100. status: response.status,
  101. headers: responseHeaders,
  102. body: responseBody,
  103. })
  104. } catch (error: any) {
  105. return res.status(500).json({
  106. status: 500,
  107. error: {
  108. message: error.message || 'Failed to test edge function',
  109. },
  110. })
  111. }
  112. }