Compare commits

...

1 Commits

Author SHA1 Message Date
abhi1992002
86b4731b90 Add detailed logging for API requests and responses 2025-07-01 09:49:04 +05:30
3 changed files with 356 additions and 58 deletions

View File

@@ -1,16 +1,30 @@
const BASE_URL = `${process.env.NEXT_PUBLIC_FRONTEND_BASE_URL}/api/proxy`; // Sending request via nextjs Server const BASE_URL = `${process.env.NEXT_PUBLIC_FRONTEND_BASE_URL}/api/proxy`; // Sending request via nextjs Server
console.log("🔧 Custom Mutator - Base URL:", BASE_URL);
console.log("🔧 Environment variables:", {
NEXT_PUBLIC_FRONTEND_BASE_URL: process.env.NEXT_PUBLIC_FRONTEND_BASE_URL,
NODE_ENV: process.env.NODE_ENV,
});
const getBody = <T>(c: Response | Request): Promise<T> => { const getBody = <T>(c: Response | Request): Promise<T> => {
const contentType = c.headers.get("content-type"); const contentType = c.headers.get("content-type");
console.log("📦 Parsing response body:", {
contentType,
headers: Object.fromEntries(c.headers.entries()),
});
if (contentType && contentType.includes("application/json")) { if (contentType && contentType.includes("application/json")) {
console.log("📄 Parsing as JSON");
return c.json(); return c.json();
} }
if (contentType && contentType.includes("application/pdf")) { if (contentType && contentType.includes("application/pdf")) {
console.log("📄 Parsing as PDF blob");
return c.blob() as Promise<T>; return c.blob() as Promise<T>;
} }
console.log("📄 Parsing as text");
return c.text() as Promise<T>; return c.text() as Promise<T>;
}; };
@@ -20,6 +34,8 @@ export const customMutator = async <T = any>(
params?: any; params?: any;
} = {}, } = {},
): Promise<T> => { ): Promise<T> => {
console.log("🚀 === CUSTOM MUTATOR START ===");
const { params, ...requestOptions } = options; const { params, ...requestOptions } = options;
const method = (requestOptions.method || "GET") as const method = (requestOptions.method || "GET") as
| "GET" | "GET"
@@ -32,6 +48,15 @@ export const customMutator = async <T = any>(
...((requestOptions.headers as Record<string, string>) || {}), ...((requestOptions.headers as Record<string, string>) || {}),
}; };
console.log("📋 Request preparation:", {
url,
method,
params,
hasBody: !!data,
bodyType: data instanceof FormData ? "FormData" : typeof data,
originalHeaders: requestOptions.headers,
});
const isFormData = data instanceof FormData; const isFormData = data instanceof FormData;
// Currently, only two content types are handled here: application/json and multipart/form-data // Currently, only two content types are handled here: application/json and multipart/form-data
@@ -43,18 +68,71 @@ export const customMutator = async <T = any>(
? "?" + new URLSearchParams(params).toString() ? "?" + new URLSearchParams(params).toString()
: ""; : "";
const response = await fetch(`${BASE_URL}${url}${queryString}`, { const finalUrl = `${BASE_URL}${url}${queryString}`;
console.log("🎯 Final request details:", {
finalUrl,
method,
headers,
queryString,
bodyPreview: isFormData
? "FormData (entries hidden)"
: data
? String(data).substring(0, 200) +
(String(data).length > 200 ? "..." : "")
: "No body",
});
try {
console.log("📡 Making fetch request...");
const response = await fetch(finalUrl, {
...requestOptions, ...requestOptions,
method, method,
headers, headers,
body: data, body: data,
}); });
console.log("📨 Response received:", {
status: response.status,
statusText: response.statusText,
ok: response.ok,
headers: Object.fromEntries(response.headers.entries()),
url: response.url,
});
const response_data = await getBody<T>(response); const response_data = await getBody<T>(response);
return { console.log("✅ Response data parsed:", {
dataType: typeof response_data,
dataPreview:
typeof response_data === "object"
? JSON.stringify(response_data).substring(0, 200) + "..."
: String(response_data).substring(0, 200),
});
const result = {
status: response.status, status: response.status,
data: response_data, data: response_data,
headers: response.headers, headers: response.headers,
} as T; } as T;
console.log("🏁 === CUSTOM MUTATOR END ===");
return result;
} catch (error) {
console.error("💥 === CUSTOM MUTATOR FAILED ===");
console.error("❌ Fetch error:", error);
console.error("❌ Error details:", {
name: error instanceof Error ? error.name : "Unknown",
message: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : "No stack trace",
cause: error instanceof Error ? error.cause : undefined,
});
console.error("❌ Request context:", {
finalUrl,
method,
headers,
});
throw error;
}
}; };

View File

@@ -7,9 +7,18 @@ import {
const BACKEND_BASE_URL = const BACKEND_BASE_URL =
process.env.NEXT_PUBLIC_AGPT_SERVER_BASE_URL || "http://localhost:8006"; process.env.NEXT_PUBLIC_AGPT_SERVER_BASE_URL || "http://localhost:8006";
console.log("🔧 Proxy Route - Backend Base URL:", BACKEND_BASE_URL);
function buildBackendUrl(path: string[], queryString: string): string { function buildBackendUrl(path: string[], queryString: string): string {
const backendPath = path.join("/"); const backendPath = path.join("/");
return `${BACKEND_BASE_URL}/${backendPath}${queryString}`; const finalUrl = `${BACKEND_BASE_URL}/${backendPath}${queryString}`;
console.log("🔗 Building backend URL:", {
path,
backendPath,
queryString,
finalUrl,
});
return finalUrl;
} }
async function handleJsonRequest( async function handleJsonRequest(
@@ -17,21 +26,37 @@ async function handleJsonRequest(
method: string, method: string,
backendUrl: string, backendUrl: string,
): Promise<any> { ): Promise<any> {
console.log("📝 Handling JSON request:", { method, backendUrl });
const payload = await req.json(); const payload = await req.json();
return await makeAuthenticatedRequest( console.log("📄 Request payload:", payload);
const result = await makeAuthenticatedRequest(
method, method,
backendUrl, backendUrl,
payload, payload,
"application/json", "application/json",
); );
console.log("✅ JSON request completed successfully");
return result;
} }
async function handleFormDataRequest( async function handleFormDataRequest(
req: NextRequest, req: NextRequest,
backendUrl: string, backendUrl: string,
): Promise<any> { ): Promise<any> {
console.log("📁 Handling FormData request:", { backendUrl });
const formData = await req.formData(); const formData = await req.formData();
return await makeAuthenticatedFileUpload(backendUrl, formData); console.log(
"📄 FormData entries:",
Array.from(formData.entries()).map(([key, value]) => ({
key,
value: value instanceof File ? `File: ${value.name}` : value,
})),
);
const result = await makeAuthenticatedFileUpload(backendUrl, formData);
console.log("✅ FormData request completed successfully");
return result;
} }
async function handleUrlEncodedRequest( async function handleUrlEncodedRequest(
@@ -39,22 +64,31 @@ async function handleUrlEncodedRequest(
method: string, method: string,
backendUrl: string, backendUrl: string,
): Promise<any> { ): Promise<any> {
console.log("🔤 Handling URL encoded request:", { method, backendUrl });
const textPayload = await req.text(); const textPayload = await req.text();
const params = new URLSearchParams(textPayload); const params = new URLSearchParams(textPayload);
const payload = Object.fromEntries(params.entries()); const payload = Object.fromEntries(params.entries());
return await makeAuthenticatedRequest( console.log("📄 URL encoded payload:", payload);
const result = await makeAuthenticatedRequest(
method, method,
backendUrl, backendUrl,
payload, payload,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
); );
console.log("✅ URL encoded request completed successfully");
return result;
} }
async function handleRequestWithoutBody( async function handleRequestWithoutBody(
method: string, method: string,
backendUrl: string, backendUrl: string,
): Promise<any> { ): Promise<any> {
return await makeAuthenticatedRequest(method, backendUrl); console.log("🚀 Handling request without body:", { method, backendUrl });
const result = await makeAuthenticatedRequest(method, backendUrl);
console.log("✅ Request without body completed successfully");
return result;
} }
function createUnsupportedContentTypeResponse( function createUnsupportedContentTypeResponse(
@@ -91,7 +125,17 @@ function createResponse(
} }
function createErrorResponse(error: unknown): NextResponse { function createErrorResponse(error: unknown): NextResponse {
console.error("API proxy error:", error); console.error("API proxy error:", error);
console.error(
"❌ Error stack:",
error instanceof Error ? error.stack : "No stack trace",
);
console.error("❌ Error details:", {
name: error instanceof Error ? error.name : "Unknown",
message: error instanceof Error ? error.message : String(error),
cause: error instanceof Error ? error.cause : undefined,
});
const detail = const detail =
error instanceof Error ? error.message : "An unknown error occurred"; error instanceof Error ? error.message : "An unknown error occurred";
return NextResponse.json( return NextResponse.json(
@@ -110,14 +154,32 @@ async function handler(
req: NextRequest, req: NextRequest,
{ params }: { params: Promise<{ path: string[] }> }, { params }: { params: Promise<{ path: string[] }> },
) { ) {
console.log("🚀 === PROXY REQUEST START ===");
const { path } = await params; const { path } = await params;
const url = new URL(req.url); const url = new URL(req.url);
const queryString = url.search; const queryString = url.search;
console.log("📋 Request details:", {
method: req.method,
originalUrl: req.url,
path,
queryString,
headers: Object.fromEntries(req.headers.entries()),
nextUrl: url.toString(),
});
const backendUrl = buildBackendUrl(path, queryString); const backendUrl = buildBackendUrl(path, queryString);
const method = req.method; const method = req.method;
const contentType = req.headers.get("Content-Type"); const contentType = req.headers.get("Content-Type");
console.log("🎯 Processing request:", {
method,
contentType,
backendUrl,
});
let responseBody: any; let responseBody: any;
const responseStatus: number = 200; const responseStatus: number = 200;
const responseHeaders: Record<string, string> = { const responseHeaders: Record<string, string> = {
@@ -126,20 +188,37 @@ async function handler(
try { try {
if (method === "GET" || method === "DELETE") { if (method === "GET" || method === "DELETE") {
console.log("🔄 Routing to handleRequestWithoutBody");
responseBody = await handleRequestWithoutBody(method, backendUrl); responseBody = await handleRequestWithoutBody(method, backendUrl);
} else if (contentType?.includes("application/json")) { } else if (contentType?.includes("application/json")) {
console.log("🔄 Routing to handleJsonRequest");
responseBody = await handleJsonRequest(req, method, backendUrl); responseBody = await handleJsonRequest(req, method, backendUrl);
} else if (contentType?.includes("multipart/form-data")) { } else if (contentType?.includes("multipart/form-data")) {
console.log("🔄 Routing to handleFormDataRequest");
responseBody = await handleFormDataRequest(req, backendUrl); responseBody = await handleFormDataRequest(req, backendUrl);
responseHeaders["Content-Type"] = "text/plain"; responseHeaders["Content-Type"] = "text/plain";
} else if (contentType?.includes("application/x-www-form-urlencoded")) { } else if (contentType?.includes("application/x-www-form-urlencoded")) {
console.log("🔄 Routing to handleUrlEncodedRequest");
responseBody = await handleUrlEncodedRequest(req, method, backendUrl); responseBody = await handleUrlEncodedRequest(req, method, backendUrl);
} else { } else {
console.log("❌ Unsupported content type:", contentType);
return createUnsupportedContentTypeResponse(contentType); return createUnsupportedContentTypeResponse(contentType);
} }
console.log("✅ Request processed successfully:", {
responseStatus,
responseHeaders,
responseBodyType: typeof responseBody,
responseBodyPreview:
typeof responseBody === "object"
? JSON.stringify(responseBody).substring(0, 200) + "..."
: String(responseBody).substring(0, 200),
});
console.log("🏁 === PROXY REQUEST END ===");
return createResponse(responseBody, responseStatus, responseHeaders); return createResponse(responseBody, responseStatus, responseHeaders);
} catch (error) { } catch (error) {
console.log("💥 === PROXY REQUEST FAILED ===");
return createErrorResponse(error); return createErrorResponse(error);
} }
} }

View File

@@ -18,25 +18,40 @@ export function buildRequestUrl(
} }
export async function getServerAuthToken(): Promise<string> { export async function getServerAuthToken(): Promise<string> {
console.log("🔐 Getting server auth token...");
const supabase = await getServerSupabase(); const supabase = await getServerSupabase();
if (!supabase) { if (!supabase) {
console.error("❌ Supabase client not available");
throw new Error("Supabase client not available"); throw new Error("Supabase client not available");
} }
console.log("✅ Supabase client obtained");
try { try {
const { const {
data: { session }, data: { session },
error, error,
} = await supabase.auth.getSession(); } = await supabase.auth.getSession();
console.log("🔍 Session check:", {
hasSession: !!session,
hasAccessToken: !!session?.access_token,
hasError: !!error,
errorMessage: error?.message,
userId: session?.user?.id,
});
if (error || !session?.access_token) { if (error || !session?.access_token) {
console.warn("⚠️ No valid session or access token found");
return "no-token-found"; return "no-token-found";
} }
console.log("✅ Valid access token obtained");
return session.access_token; return session.access_token;
} catch (error) { } catch (error) {
console.error("Failed to get auth token:", error); console.error("Failed to get auth token:", error);
return "no-token-found"; return "no-token-found";
} }
} }
@@ -46,6 +61,16 @@ export function createRequestHeaders(
hasRequestBody: boolean, hasRequestBody: boolean,
contentType: string = "application/json", contentType: string = "application/json",
): Record<string, string> { ): Record<string, string> {
console.log("📋 Creating request headers:", {
hasToken: token !== "no-token-found",
tokenPreview:
token !== "no-token-found"
? `${token.substring(0, 10)}...`
: "no-token-found",
hasRequestBody,
contentType,
});
const headers: Record<string, string> = {}; const headers: Record<string, string> = {};
if (hasRequestBody) { if (hasRequestBody) {
@@ -56,6 +81,12 @@ export function createRequestHeaders(
headers["Authorization"] = `Bearer ${token}`; headers["Authorization"] = `Bearer ${token}`;
} }
console.log("🏷️ Headers created:", {
headerKeys: Object.keys(headers),
hasAuth: !!headers["Authorization"],
hasContentType: !!headers["Content-Type"],
});
return headers; return headers;
} }
@@ -157,20 +188,60 @@ export async function makeAuthenticatedRequest(
payload?: Record<string, any>, payload?: Record<string, any>,
contentType: string = "application/json", contentType: string = "application/json",
): Promise<any> { ): Promise<any> {
console.log("🔐 === AUTHENTICATED REQUEST START ===");
console.log("📋 Request details:", {
method,
url,
contentType,
hasPayload: !!payload,
payloadPreview: payload
? JSON.stringify(payload).substring(0, 100) + "..."
: "No payload",
});
const token = await getServerAuthToken(); const token = await getServerAuthToken();
const payloadAsQuery = ["GET", "DELETE"].includes(method); const payloadAsQuery = ["GET", "DELETE"].includes(method);
const hasRequestBody = !payloadAsQuery && payload !== undefined; const hasRequestBody = !payloadAsQuery && payload !== undefined;
console.log("🎯 Request configuration:", {
payloadAsQuery,
hasRequestBody,
tokenAvailable: token !== "no-token-found",
});
const headers = createRequestHeaders(token, hasRequestBody, contentType);
const body = hasRequestBody
? serializeRequestBody(payload, contentType)
: undefined;
console.log("📡 Making fetch request to:", url);
console.log(
"📤 Request body preview:",
body ? String(body).substring(0, 200) + "..." : "No body",
);
try {
const response = await fetch(url, { const response = await fetch(url, {
method, method,
headers: createRequestHeaders(token, hasRequestBody, contentType), headers,
body: hasRequestBody body,
? serializeRequestBody(payload, contentType) });
: undefined,
console.log("📨 Response received:", {
status: response.status,
statusText: response.statusText,
ok: response.ok,
headers: Object.fromEntries(response.headers.entries()),
url: response.url,
}); });
if (!response.ok) { if (!response.ok) {
const errorDetail = await parseApiError(response); const errorDetail = await parseApiError(response);
console.error("❌ Request failed:", {
status: response.status,
statusText: response.statusText,
errorDetail,
});
// Handle authentication errors gracefully during logout // Handle authentication errors gracefully during logout
if (isAuthenticationError(response, errorDetail)) { if (isAuthenticationError(response, errorDetail)) {
@@ -193,13 +264,45 @@ export async function makeAuthenticatedRequest(
throw new Error(errorDetail); throw new Error(errorDetail);
} }
return parseApiResponse(response); const responseData = await parseApiResponse(response);
console.log("✅ Request completed successfully");
console.log(
"📦 Response data preview:",
responseData
? JSON.stringify(responseData).substring(0, 200) + "..."
: "No data",
);
console.log("🏁 === AUTHENTICATED REQUEST END ===");
return responseData;
} catch (error) {
console.error("💥 === AUTHENTICATED REQUEST FAILED ===");
console.error("❌ Fetch error:", error);
console.error("❌ Error details:", {
name: error instanceof Error ? error.name : "Unknown",
message: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : "No stack trace",
});
throw error;
}
} }
export async function makeAuthenticatedFileUpload( export async function makeAuthenticatedFileUpload(
url: string, url: string,
formData: FormData, formData: FormData,
): Promise<string> { ): Promise<string> {
console.log("📁 === AUTHENTICATED FILE UPLOAD START ===");
console.log("📋 Upload details:", {
url,
formDataEntries: Array.from(formData.entries()).map(([key, value]) => ({
key,
value:
value instanceof File
? `File: ${value.name} (${value.size} bytes)`
: value,
})),
});
const token = await getServerAuthToken(); const token = await getServerAuthToken();
const headers: Record<string, string> = {}; const headers: Record<string, string> = {};
@@ -207,6 +310,14 @@ export async function makeAuthenticatedFileUpload(
headers["Authorization"] = `Bearer ${token}`; headers["Authorization"] = `Bearer ${token}`;
} }
console.log("🏷️ Upload headers:", {
hasAuth: !!headers["Authorization"],
headerKeys: Object.keys(headers),
});
console.log("📡 Making file upload request to:", url);
try {
// Don't set Content-Type for FormData - let the browser set it with boundary // Don't set Content-Type for FormData - let the browser set it with boundary
const response = await fetch(url, { const response = await fetch(url, {
method: "POST", method: "POST",
@@ -214,9 +325,21 @@ export async function makeAuthenticatedFileUpload(
body: formData, body: formData,
}); });
console.log("📨 Upload response received:", {
status: response.status,
statusText: response.statusText,
ok: response.ok,
headers: Object.fromEntries(response.headers.entries()),
});
if (!response.ok) { if (!response.ok) {
// Handle authentication errors gracefully for file uploads too // Handle authentication errors gracefully for file uploads too
const errorMessage = `Error uploading file: ${response.statusText}`; const errorMessage = `Error uploading file: ${response.statusText}`;
console.error("❌ File upload failed:", {
status: response.status,
statusText: response.statusText,
errorMessage,
});
if (response.status === 401 || response.status === 403) { if (response.status === 401 || response.status === 403) {
if (isLogoutInProgress()) { if (isLogoutInProgress()) {
@@ -232,5 +355,23 @@ export async function makeAuthenticatedFileUpload(
throw new Error(errorMessage); throw new Error(errorMessage);
} }
return await response.text(); const responseText = await response.text();
console.log("✅ File upload completed successfully");
console.log(
"📦 Upload response preview:",
responseText.substring(0, 200) + "...",
);
console.log("🏁 === AUTHENTICATED FILE UPLOAD END ===");
return responseText;
} catch (error) {
console.error("💥 === AUTHENTICATED FILE UPLOAD FAILED ===");
console.error("❌ Upload error:", error);
console.error("❌ Error details:", {
name: error instanceof Error ? error.name : "Unknown",
message: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : "No stack trace",
});
throw error;
}
} }