chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
const MUAPI_BASE = 'https://api.muapi.ai';
|
||||
|
||||
function getApiKey(request) {
|
||||
// Only accept x-api-key header. Cookie-based auth is removed for security:
|
||||
// cookies without HttpOnly flag can be stolen by XSS (CWE-522).
|
||||
const headerKey = request.headers.get('x-api-key');
|
||||
return headerKey || null;
|
||||
}
|
||||
|
||||
function cleanHeaders(request) {
|
||||
const headers = new Headers(request.headers);
|
||||
headers.delete('host');
|
||||
headers.delete('connection');
|
||||
headers.delete('cookie'); // CRITICAL: Stop forwarding browser cookies to MuAPI
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Build the target URL without a trailing slash when path is empty.
|
||||
// e.g. GET /api/agents?is_template=true → https://api.muapi.ai/agents?is_template=true
|
||||
// e.g. GET /api/agents/by-slug/foo → https://api.muapi.ai/agents/by-slug/foo
|
||||
function buildTargetUrl(pathSegments, search) {
|
||||
const path = pathSegments.join('/');
|
||||
const base = `${MUAPI_BASE}/agents`;
|
||||
return path ? `${base}/${path}${search}` : `${base}${search}`;
|
||||
}
|
||||
|
||||
export async function GET(request, { params }) {
|
||||
const slug = await params;
|
||||
const pathSegments = slug.path || [];
|
||||
const { search } = new URL(request.url);
|
||||
const targetUrl = buildTargetUrl(pathSegments, search);
|
||||
|
||||
const headers = cleanHeaders(request);
|
||||
const apiKey = getApiKey(request);
|
||||
// NOTE: credential logging removed for security (CWE-200)
|
||||
if (apiKey) headers.set('x-api-key', apiKey);
|
||||
|
||||
try {
|
||||
const response = await fetch(targetUrl, { headers, method: 'GET' });
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request, { params }) {
|
||||
const slug = await params;
|
||||
const pathSegments = slug.path || [];
|
||||
const { search } = new URL(request.url);
|
||||
const targetUrl = buildTargetUrl(pathSegments, search);
|
||||
|
||||
const headers = cleanHeaders(request);
|
||||
const apiKey = getApiKey(request);
|
||||
// NOTE: credential logging removed for security (CWE-200)
|
||||
if (apiKey) headers.set('x-api-key', apiKey);
|
||||
|
||||
try {
|
||||
const body = await request.arrayBuffer();
|
||||
const response = await fetch(targetUrl, { method: 'POST', headers, body });
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request, { params }) {
|
||||
const slug = await params;
|
||||
const pathSegments = slug.path || [];
|
||||
const { search } = new URL(request.url);
|
||||
const targetUrl = buildTargetUrl(pathSegments, search);
|
||||
|
||||
const headers = cleanHeaders(request);
|
||||
const apiKey = getApiKey(request);
|
||||
if (apiKey) headers.set('x-api-key', apiKey);
|
||||
|
||||
try {
|
||||
const response = await fetch(targetUrl, { method: 'DELETE', headers });
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request, { params }) {
|
||||
const slug = await params;
|
||||
const pathSegments = slug.path || [];
|
||||
const { search } = new URL(request.url);
|
||||
const targetUrl = buildTargetUrl(pathSegments, search);
|
||||
|
||||
const headers = cleanHeaders(request);
|
||||
const apiKey = getApiKey(request);
|
||||
if (apiKey) headers.set('x-api-key', apiKey);
|
||||
|
||||
try {
|
||||
const body = await request.arrayBuffer();
|
||||
const response = await fetch(targetUrl, { method: 'PUT', headers, body });
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user