ai-wpa/lib/proxy.ts

127 lines
3.4 KiB
TypeScript

/**
* Development proxy configuration
* Useful for proxying external APIs during development
*/
import { NextRequest, NextResponse } from 'next/server'
export interface ProxyConfig {
target: string
pathRewrite?: Record<string, string>
changeOrigin?: boolean
headers?: Record<string, string>
}
/**
* Simple proxy utility for API routes
* @param request - The incoming request
* @param config - Proxy configuration
*/
export async function proxyRequest(
request: NextRequest,
config: ProxyConfig
): Promise<NextResponse> {
try {
const url = new URL(request.url)
let targetPath = url.pathname
// Apply path rewrites
if (config.pathRewrite) {
Object.entries(config.pathRewrite).forEach(([pattern, replacement]) => {
const regex = new RegExp(pattern)
if (regex.test(targetPath)) {
targetPath = targetPath.replace(regex, replacement)
}
})
}
// Build target URL
const targetUrl = new URL(targetPath + url.search, config.target)
// Prepare headers
const headers = new Headers()
// Copy headers from original request
request.headers.forEach((value, key) => {
// Skip host header to avoid conflicts
if (key.toLowerCase() !== 'host') {
headers.set(key, value)
}
})
// Add custom headers
if (config.headers) {
Object.entries(config.headers).forEach(([key, value]) => {
headers.set(key, value)
})
}
// Change origin if specified
if (config.changeOrigin) {
headers.set('Host', targetUrl.host)
headers.set('Origin', config.target)
}
// Forward the request
const response = await fetch(targetUrl.toString(), {
method: request.method,
headers,
body:
request.method !== 'GET' && request.method !== 'HEAD'
? await request.arrayBuffer()
: undefined,
})
// Create response with proper headers
const responseHeaders = new Headers()
// Copy response headers
response.headers.forEach((value, key) => {
// Skip some headers that might cause issues
if (
!['content-encoding', 'content-length', 'transfer-encoding'].includes(key.toLowerCase())
) {
responseHeaders.set(key, value)
}
})
// Add CORS headers for development
if (process.env.NODE_ENV === 'development') {
responseHeaders.set('Access-Control-Allow-Origin', '*')
responseHeaders.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
responseHeaders.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
}
const responseBody = await response.arrayBuffer()
return new NextResponse(responseBody, {
status: response.status,
statusText: response.statusText,
headers: responseHeaders,
})
} catch (error) {
console.error('Proxy error:', error)
return NextResponse.json({ error: 'Proxy request failed' }, { status: 500 })
}
}
/**
* Example usage in an API route:
*
* // app/api/proxy/external/route.ts
* import { proxyRequest } from '@/lib/proxy';
*
* export async function GET(request: NextRequest) {
* return proxyRequest(request, {
* target: 'https://api.external-service.com',
* pathRewrite: {
* '^/api/proxy/external': ''
* },
* changeOrigin: true,
* headers: {
* 'X-API-Key': process.env.EXTERNAL_API_KEY || ''
* }
* });
* }
*/