From 672333a6db77be9d46675131d7ad7c966fe7b829 Mon Sep 17 00:00:00 2001 From: alma Date: Sat, 17 Jan 2026 03:05:38 +0100 Subject: [PATCH] Fondation --- app/api/rocket-chat/messages/route.ts | 25 +++-- app/api/rocket-chat/user-token/route.ts | 118 ++++++++++++++++++++---- components/parole.tsx | 33 ++++++- lib/utils/fetch-with-timeout.ts | 28 +++++- 4 files changed, 173 insertions(+), 31 deletions(-) diff --git a/app/api/rocket-chat/messages/route.ts b/app/api/rocket-chat/messages/route.ts index ce5d7bf..fc556bb 100644 --- a/app/api/rocket-chat/messages/route.ts +++ b/app/api/rocket-chat/messages/route.ts @@ -98,11 +98,20 @@ export async function GET(request: Request) { } // Get all users to find the current user - const usersData = await fetchJsonWithTimeout(`${baseUrl}/api/v1/users.list`, { - method: 'GET', - timeout: 10000, // 10 seconds - headers: adminHeaders - }); + let usersData; + try { + usersData = await fetchJsonWithTimeout(`${baseUrl}/api/v1/users.list`, { + method: 'GET', + timeout: 10000, // 10 seconds + headers: adminHeaders + }); + } catch (error) { + logger.error('[ROCKET_CHAT] Error fetching users list', { + error: error instanceof Error ? error.message : String(error), + }); + // Return empty messages instead of failing completely + return NextResponse.json({ messages: [] }, { status: 200 }); + } if (!usersData.success) { logger.error('[ROCKET_CHAT] Failed to get users list', { @@ -248,10 +257,14 @@ export async function GET(request: Request) { } ); } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); logger.error('[ROCKET_CHAT] Failed to get messages for room', { roomName: subscription.name, - error: error instanceof Error ? error.message : String(error), + roomId: subscription.rid, + endpoint, + error: errorMessage, }); + // Continue to next room instead of failing completely continue; } logger.debug('[ROCKET_CHAT] Messages for room', { diff --git a/app/api/rocket-chat/user-token/route.ts b/app/api/rocket-chat/user-token/route.ts index 67f0416..cf6e157 100644 --- a/app/api/rocket-chat/user-token/route.ts +++ b/app/api/rocket-chat/user-token/route.ts @@ -45,20 +45,60 @@ export async function GET(request: Request) { } // Get all users to find the current user - const usersResponse = await fetch(`${baseUrl}/api/v1/users.list`, { - method: 'GET', - headers: adminHeaders - }); - - if (!usersResponse.ok) { - logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to get users list'); + let usersResponse; + try { + usersResponse = await fetch(`${baseUrl}/api/v1/users.list`, { + method: 'GET', + headers: adminHeaders + }); + } catch (error) { + logger.error('[ROCKET_CHAT_USER_TOKEN] Error fetching users list', { + error: error instanceof Error ? error.message : String(error), + }); return NextResponse.json( - { error: 'Failed to get user' }, + { error: 'Failed to connect to RocketChat' }, { status: 500 } ); } - const usersData = await usersResponse.json(); + if (!usersResponse.ok) { + const errorText = await usersResponse.text().catch(() => 'Unknown error'); + logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to get users list', { + status: usersResponse.status, + statusText: usersResponse.statusText, + errorPreview: errorText.substring(0, 200), + }); + return NextResponse.json( + { error: 'Failed to get user list from RocketChat' }, + { status: 500 } + ); + } + + const contentType = usersResponse.headers.get('content-type') || ''; + if (!contentType.includes('application/json')) { + const errorText = await usersResponse.text().catch(() => 'Unknown error'); + logger.error('[ROCKET_CHAT_USER_TOKEN] Expected JSON, got HTML', { + contentType, + errorPreview: errorText.substring(0, 200), + }); + return NextResponse.json( + { error: 'RocketChat returned invalid response format' }, + { status: 500 } + ); + } + + let usersData; + try { + usersData = await usersResponse.json(); + } catch (error) { + logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to parse users list JSON', { + error: error instanceof Error ? error.message : String(error), + }); + return NextResponse.json( + { error: 'Failed to parse RocketChat response' }, + { status: 500 } + ); + } const currentUser = usersData.users?.find((u: any) => u.username?.toLowerCase() === username.toLowerCase() || u.emails?.some((e: any) => e.address?.toLowerCase() === session.user.email?.toLowerCase()) @@ -82,24 +122,64 @@ export async function GET(request: Request) { ); } - const createTokenResponse = await fetch(`${baseUrl}/api/v1/users.createToken`, { - method: 'POST', - headers: adminHeaders, - body: JSON.stringify({ - userId: currentUser._id, - secret: secret - }) - }); + let createTokenResponse; + try { + createTokenResponse = await fetch(`${baseUrl}/api/v1/users.createToken`, { + method: 'POST', + headers: adminHeaders, + body: JSON.stringify({ + userId: currentUser._id, + secret: secret + }) + }); + } catch (error) { + logger.error('[ROCKET_CHAT_USER_TOKEN] Error creating token', { + error: error instanceof Error ? error.message : String(error), + }); + return NextResponse.json( + { error: 'Failed to connect to RocketChat' }, + { status: 500 } + ); + } if (!createTokenResponse.ok) { - logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to create user token'); + const errorText = await createTokenResponse.text().catch(() => 'Unknown error'); + logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to create user token', { + status: createTokenResponse.status, + statusText: createTokenResponse.statusText, + errorPreview: errorText.substring(0, 200), + }); return NextResponse.json( { error: 'Failed to create token' }, { status: 500 } ); } - const tokenData = await createTokenResponse.json(); + const contentType = createTokenResponse.headers.get('content-type') || ''; + if (!contentType.includes('application/json')) { + const errorText = await createTokenResponse.text().catch(() => 'Unknown error'); + logger.error('[ROCKET_CHAT_USER_TOKEN] Expected JSON, got HTML', { + contentType, + errorPreview: errorText.substring(0, 200), + }); + return NextResponse.json( + { error: 'RocketChat returned invalid response format' }, + { status: 500 } + ); + } + + let tokenData; + try { + tokenData = await createTokenResponse.json(); + } catch (error) { + logger.error('[ROCKET_CHAT_USER_TOKEN] Failed to parse token JSON', { + error: error instanceof Error ? error.message : String(error), + }); + return NextResponse.json( + { error: 'Failed to parse RocketChat response' }, + { status: 500 } + ); + } logger.debug('[ROCKET_CHAT_USER_TOKEN] Token created', { emailHash: Buffer.from(session.user.email.toLowerCase()).toString('base64').slice(0, 12), diff --git a/components/parole.tsx b/components/parole.tsx index 82993f5..116c63d 100644 --- a/components/parole.tsx +++ b/components/parole.tsx @@ -67,8 +67,32 @@ export function Parole() { }); if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to fetch messages'); + // Check if response is JSON before trying to parse + const contentType = response.headers.get('content-type') || ''; + if (contentType.includes('application/json')) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to fetch messages'); + } else { + // Response is HTML (probably an error page) + const errorText = await response.text(); + console.error('[Parole Widget] Received HTML instead of JSON', { + status: response.status, + statusText: response.statusText, + preview: errorText.substring(0, 200), + }); + throw new Error(`Server returned error page (${response.status})`); + } + } + + // Check if response is JSON before parsing + const contentType = response.headers.get('content-type') || ''; + if (!contentType.includes('application/json')) { + const errorText = await response.text(); + console.error('[Parole Widget] Expected JSON, got HTML', { + contentType, + preview: errorText.substring(0, 200), + }); + throw new Error('Server returned invalid response format'); } const data = await response.json(); @@ -153,6 +177,11 @@ export function Parole() { } setError(null); } catch (err) { + const errorMessage = err instanceof Error ? err.message : String(err); + console.error('[Parole Widget] Error fetching messages', { + error: errorMessage, + forceRefresh, + }); console.error('Error fetching messages:', err); const errorMessage = err instanceof Error ? err.message : 'Failed to fetch messages'; setError(errorMessage); diff --git a/lib/utils/fetch-with-timeout.ts b/lib/utils/fetch-with-timeout.ts index 162bfc5..d166925 100644 --- a/lib/utils/fetch-with-timeout.ts +++ b/lib/utils/fetch-with-timeout.ts @@ -85,10 +85,30 @@ export async function fetchJsonWithTimeout( ); } - const contentType = response.headers.get('content-type'); - if (!contentType || !contentType.includes('application/json')) { - throw new Error(`Expected JSON response, got ${contentType}`); + const contentType = response.headers.get('content-type') || ''; + + // Check if response is JSON + if (!contentType.includes('application/json')) { + // Try to read the response text to see what we got + const responseText = await response.text().catch(() => 'Unable to read response'); + const preview = responseText.substring(0, 200); + + // If it looks like HTML, provide a more helpful error + if (responseText.trim().startsWith(' 'Unable to read response'); + throw new Error(`Failed to parse JSON response. Content: ${responseText.substring(0, 200)}`); + } }