94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
// Example Next.js API route for proxying SSE connections
|
|
// File: app/api/proxy/sse/[...path]/route.ts
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
import https from 'https';
|
|
|
|
/**
|
|
* Proxy endpoint for SSE connections
|
|
* This endpoint forwards requests to the SSE endpoint and streams the response back to the client
|
|
*/
|
|
export async function GET(
|
|
request: NextRequest,
|
|
{ params }: { params: { path: string[] } }
|
|
) {
|
|
try {
|
|
// Get the path from the request
|
|
const path = params.path.join('/');
|
|
|
|
// Get the API base URL from environment variables
|
|
const apiBaseUrl = process.env.API_ENDPOINT || 'https://api.example.com';
|
|
|
|
// Construct the target URL
|
|
const targetUrl = `${apiBaseUrl}/events/orders/${path}`;
|
|
|
|
// Get the auth header from the request
|
|
const authHeader = request.headers.get('X-Signed-Auth');
|
|
|
|
// Create headers for the proxy request
|
|
const headers: HeadersInit = {
|
|
'Accept': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
};
|
|
|
|
// Add auth header if available
|
|
if (authHeader) {
|
|
headers['X-Signed-Auth'] = authHeader;
|
|
}
|
|
|
|
// Make the request to the target URL
|
|
const response = await fetch(targetUrl, {
|
|
method: 'GET',
|
|
headers,
|
|
// Don't verify SSL in development or when explicitly configured
|
|
...((process.env.NODE_ENV === 'development' || process.env.SKIP_SSL_VALIDATION === 'true') && {
|
|
//@ts-ignore
|
|
agent: new https.Agent({ rejectUnauthorized: false }),
|
|
}),
|
|
});
|
|
|
|
// If the response is not OK, return an error
|
|
if (!response.ok) {
|
|
return NextResponse.json(
|
|
{ error: 'Failed to connect to SSE endpoint' },
|
|
{ status: response.status }
|
|
);
|
|
}
|
|
|
|
// Get the response body as a readable stream
|
|
const body = response.body;
|
|
|
|
// If the body is null, return an error
|
|
if (!body) {
|
|
return NextResponse.json(
|
|
{ error: 'Response body is null' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
|
|
// Create a new response with the body stream
|
|
const newResponse = new NextResponse(body);
|
|
|
|
// Copy headers from the original response
|
|
response.headers.forEach((value, key) => {
|
|
newResponse.headers.set(key, value);
|
|
});
|
|
|
|
// Set required headers for SSE
|
|
newResponse.headers.set('Content-Type', 'text/event-stream');
|
|
newResponse.headers.set('Cache-Control', 'no-cache');
|
|
newResponse.headers.set('Connection', 'keep-alive');
|
|
|
|
return newResponse;
|
|
} catch (error) {
|
|
console.error('Error in SSE proxy:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Internal server error' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
// Disable response caching
|
|
export const dynamic = 'force-dynamic';
|