testapp: enhance logging and error handling across services and controllers
This commit is contained in:
parent
75fbeea807
commit
160cb3927d
63
.github/workflows/wc-e2e-test.yaml
vendored
63
.github/workflows/wc-e2e-test.yaml
vendored
@ -140,6 +140,20 @@ jobs:
|
||||
env:
|
||||
RUN_MODE: CI
|
||||
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
|
||||
- name: Collect TestApp logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "=== Collecting TestApp logs ==="
|
||||
if [ -f testapp/testapp.log ]; then
|
||||
echo "TestApp log file found, copying..."
|
||||
cp testapp/testapp.log testapp-logs-webhooks.log
|
||||
else
|
||||
echo "TestApp log file not found at testapp/testapp.log"
|
||||
echo "Looking for log files..."
|
||||
find . -name "testapp.log" -type f 2>/dev/null || echo "No testapp.log files found"
|
||||
echo "Creating empty log file for artifact upload"
|
||||
echo "TestApp log file not found during CI run" > testapp-logs-webhooks.log
|
||||
fi
|
||||
- name: Upload failed test videos
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
@ -148,6 +162,13 @@ jobs:
|
||||
path: |
|
||||
frontend/webcomponent/test-results/
|
||||
retention-days: 2
|
||||
- name: Upload TestApp logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: testapp-logs-webhooks-functionality
|
||||
path: testapp-logs-webhooks.log
|
||||
retention-days: 2
|
||||
- name: Clean up
|
||||
if: always()
|
||||
uses: OpenVidu/actions/cleanup@main
|
||||
@ -190,6 +211,20 @@ jobs:
|
||||
env:
|
||||
RUN_MODE: CI
|
||||
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
|
||||
- name: Collect TestApp logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "=== Collecting TestApp logs ==="
|
||||
if [ -f testapp/testapp.log ]; then
|
||||
echo "TestApp log file found, copying..."
|
||||
cp testapp/testapp.log testapp-logs-ui-features.log
|
||||
else
|
||||
echo "TestApp log file not found at testapp/testapp.log"
|
||||
echo "Looking for log files..."
|
||||
find . -name "testapp.log" -type f 2>/dev/null || echo "No testapp.log files found"
|
||||
echo "Creating empty log file for artifact upload"
|
||||
echo "TestApp log file not found during CI run" > testapp-logs-ui-features.log
|
||||
fi
|
||||
- name: Upload failed test videos
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
@ -198,6 +233,13 @@ jobs:
|
||||
path: |
|
||||
frontend/webcomponent/test-results/
|
||||
retention-days: 2
|
||||
- name: Upload TestApp logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: testapp-logs-ui-features
|
||||
path: testapp-logs-ui-features.log
|
||||
retention-days: 2
|
||||
- name: Clean up
|
||||
if: always()
|
||||
uses: OpenVidu/actions/cleanup@main
|
||||
@ -240,6 +282,20 @@ jobs:
|
||||
env:
|
||||
RUN_MODE: CI
|
||||
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
|
||||
- name: Collect TestApp logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "=== Collecting TestApp logs ==="
|
||||
if [ -f testapp/testapp.log ]; then
|
||||
echo "TestApp log file found, copying..."
|
||||
cp testapp/testapp.log testapp-logs-recording-access.log
|
||||
else
|
||||
echo "TestApp log file not found at testapp/testapp.log"
|
||||
echo "Looking for log files..."
|
||||
find . -name "testapp.log" -type f 2>/dev/null || echo "No testapp.log files found"
|
||||
echo "Creating empty log file for artifact upload"
|
||||
echo "TestApp log file not found during CI run" > testapp-logs-recording-access.log
|
||||
fi
|
||||
- name: Dump TestApp logs on failure
|
||||
if: failure()
|
||||
run: |
|
||||
@ -256,6 +312,13 @@ jobs:
|
||||
path: |
|
||||
frontend/webcomponent/test-results/
|
||||
retention-days: 2
|
||||
- name: Upload TestApp logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: testapp-logs-recording-access
|
||||
path: testapp-logs-recording-access.log
|
||||
retention-days: 2
|
||||
- name: Dump OpenVidu Local Deployment logs
|
||||
if: always()
|
||||
shell: bash
|
||||
|
||||
@ -4,6 +4,9 @@ import { deleteAllRecordings, getAllRecordings } from '../services/recordingServ
|
||||
|
||||
export const getHome = async (_req: Request, res: Response) => {
|
||||
try {
|
||||
console.log('Fetching rooms from:', `${process.env.MEET_API_URL || 'http://localhost:6080/api/v1'}/rooms`);
|
||||
console.log('Using API key:', process.env.MEET_API_KEY || 'meet-api-key');
|
||||
|
||||
const { rooms } = await getAllRooms();
|
||||
|
||||
// Sort rooms by newest first
|
||||
@ -13,44 +16,78 @@ export const getHome = async (_req: Request, res: Response) => {
|
||||
return dateB.getTime() - dateA.getTime();
|
||||
});
|
||||
|
||||
console.log(`Rooms fetched: ${rooms.length}`);
|
||||
console.log(`Rooms fetched successfully: ${rooms.length}`);
|
||||
res.render('index', { rooms });
|
||||
} catch (error) {
|
||||
console.error('Error fetching rooms:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
console.error('Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace',
|
||||
apiUrl: process.env.MEET_API_URL || 'http://localhost:6080/api/v1',
|
||||
apiKey: process.env.MEET_API_KEY || 'meet-api-key'
|
||||
});
|
||||
res.status(500).send('Internal Server Error - Failed to fetch rooms: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export const postCreateRoom = async (req: Request, res: Response) => {
|
||||
try {
|
||||
console.log('Creating room with body:', JSON.stringify(req.body, null, 2));
|
||||
const { roomIdPrefix, autoDeletionDate } = req.body;
|
||||
const preferences = processFormPreferences(req.body);
|
||||
|
||||
await createRoom({ roomIdPrefix, autoDeletionDate, preferences });
|
||||
console.log('Processed preferences:', JSON.stringify(preferences, null, 2));
|
||||
console.log('Room creation parameters:', { roomIdPrefix, autoDeletionDate });
|
||||
|
||||
const result = await createRoom({ roomIdPrefix, autoDeletionDate, preferences });
|
||||
console.log('Room created successfully:', result);
|
||||
res.redirect('/');
|
||||
} catch (error) {
|
||||
console.error('Error creating room:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
console.error('Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace',
|
||||
requestBody: req.body
|
||||
});
|
||||
res.status(500).send('Internal Server Error - Failed to create room: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteRoomCtrl = async (req: Request, res: Response) => {
|
||||
try {
|
||||
console.log('Deleting room with body:', JSON.stringify(req.body, null, 2));
|
||||
const { roomId } = req.body;
|
||||
|
||||
if (!roomId) {
|
||||
console.error('No roomId provided for deletion');
|
||||
res.status(400).send('Bad Request - roomId is required');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Attempting to delete room: ${roomId}`);
|
||||
await deleteRoom(roomId);
|
||||
console.log(`Room ${roomId} deleted successfully`);
|
||||
res.redirect('/');
|
||||
} catch (error) {
|
||||
console.error('Error deleting room:', error);
|
||||
res.status(500).send('Internal Server Error');
|
||||
console.error('Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace',
|
||||
requestBody: req.body
|
||||
});
|
||||
res.status(500).send('Internal Server Error - Failed to delete room: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteAllRoomsCtrl = async (_req: Request, res: Response) => {
|
||||
try {
|
||||
console.log('Deleting all rooms...');
|
||||
const allRooms = await getAllRooms();
|
||||
console.log(`Found ${allRooms.rooms.length} rooms to delete`);
|
||||
|
||||
if (allRooms.rooms.length === 0) {
|
||||
console.log('No rooms to delete');
|
||||
res.render('index', { rooms: [] });
|
||||
@ -58,32 +95,45 @@ export const deleteAllRoomsCtrl = async (_req: Request, res: Response) => {
|
||||
}
|
||||
|
||||
const roomIds = allRooms.rooms.map((room) => room.roomId);
|
||||
console.log(`Deleting ${roomIds.length} rooms`, roomIds);
|
||||
console.log(`Deleting ${roomIds.length} rooms:`, roomIds);
|
||||
await deleteAllRooms(roomIds);
|
||||
console.log('All rooms deleted successfully');
|
||||
res.render('index', { rooms: [] });
|
||||
} catch (error) {
|
||||
console.error('Error deleting all rooms:', error);
|
||||
res.status(500).send('Internal Server Error ' + JSON.stringify(error));
|
||||
console.error('Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace'
|
||||
});
|
||||
res.status(500).send('Internal Server Error - Failed to delete all rooms: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteAllRecordingsCtrl = async (_req: Request, res: Response) => {
|
||||
try {
|
||||
console.log('Deleting all recordings...');
|
||||
const [{ recordings }, { rooms }] = await Promise.all([getAllRecordings(), getAllRooms()]);
|
||||
console.log(`Found ${recordings.length} recordings to delete`);
|
||||
|
||||
if (recordings.length === 0) {
|
||||
console.log('No recordings to delete');
|
||||
res.render('index', { rooms });
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const recordingIds = recordings.map((recording) => recording.recordingId);
|
||||
console.log(`Deleting ${recordingIds.length} recordings:`, recordingIds);
|
||||
await deleteAllRecordings(recordingIds);
|
||||
console.log(`Deleted ${recordingIds.length} recordings`);
|
||||
console.log('All recordings deleted successfully');
|
||||
res.render('index', { rooms });
|
||||
} catch (error) {
|
||||
console.error('Error deleting all recordings:', error);
|
||||
res.status(500).send('Internal Server Error ' + JSON.stringify(error));
|
||||
console.error('Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack trace'
|
||||
});
|
||||
res.status(500).send('Internal Server Error - Failed to delete all recordings: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { Server as IOServer } from 'socket.io';
|
||||
import {
|
||||
deleteAllRecordingsCtrl,
|
||||
@ -12,6 +13,43 @@ import {
|
||||
import { handleWebhook, joinRoom } from './controllers/roomController';
|
||||
import { configService } from './services/configService';
|
||||
|
||||
// Setup log file for CI debugging
|
||||
const logStream = fs.createWriteStream(path.join(__dirname, '../../testapp.log'), { flags: 'a' });
|
||||
|
||||
// Override console methods to also write to log file
|
||||
const originalConsoleLog = console.log;
|
||||
const originalConsoleError = console.error;
|
||||
const originalConsoleWarn = console.warn;
|
||||
|
||||
console.log = (...args: any[]) => {
|
||||
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' ');
|
||||
const timestamp = new Date().toISOString();
|
||||
logStream.write(`[${timestamp}] LOG: ${message}\n`);
|
||||
originalConsoleLog.apply(console, args);
|
||||
};
|
||||
|
||||
console.error = (...args: any[]) => {
|
||||
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' ');
|
||||
const timestamp = new Date().toISOString();
|
||||
logStream.write(`[${timestamp}] ERROR: ${message}\n`);
|
||||
originalConsoleError.apply(console, args);
|
||||
};
|
||||
|
||||
console.warn = (...args: any[]) => {
|
||||
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' ');
|
||||
const timestamp = new Date().toISOString();
|
||||
logStream.write(`[${timestamp}] WARN: ${message}\n`);
|
||||
originalConsoleWarn.apply(console, args);
|
||||
};
|
||||
|
||||
console.log('=== TESTAPP STARTUP ===');
|
||||
console.log('Testapp initializing at:', new Date().toISOString());
|
||||
console.log('Environment variables:');
|
||||
console.log('MEET_API_URL:', process.env.MEET_API_URL);
|
||||
console.log('MEET_API_KEY:', process.env.MEET_API_KEY ? '***SET***' : 'NOT SET');
|
||||
console.log('NODE_ENV:', process.env.NODE_ENV);
|
||||
console.log('PORT:', process.env.PORT);
|
||||
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
const io = new IOServer(server);
|
||||
@ -46,10 +84,36 @@ server.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
console.log(`Visit http://localhost:${PORT}/ to access the app`);
|
||||
console.log('-----------------------------------------');
|
||||
console.log('Configuration:');
|
||||
console.log(` MEET_API_URL: ${configService.meetApiUrl}`);
|
||||
console.log(` MEET_API_KEY: ${configService.meetApiKey ? '[SET]' : '[NOT SET]'}`);
|
||||
console.log(` MEET_WEBCOMPONENT_SRC: ${configService.meetWebhookSrc}`);
|
||||
console.log(` SERVER_PORT: ${configService.serverPort}`);
|
||||
console.log('-----------------------------------------');
|
||||
console.log('');
|
||||
|
||||
console.log('OpenVidu Meet Configuration:');
|
||||
console.log(`Meet API URL: ${configService.meetApiUrl}`);
|
||||
console.log(`Meet API key: ${configService.meetApiKey}`);
|
||||
console.log(`Meet Webcomponent Source: ${configService.meetWebhookSrc}`);
|
||||
console.log('=== TESTAPP STARTUP COMPLETE ===');
|
||||
});
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('=== TESTAPP SHUTDOWN ===');
|
||||
console.log('Received SIGTERM, shutting down gracefully');
|
||||
logStream.end();
|
||||
server.close(() => {
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
console.log('=== TESTAPP SHUTDOWN ===');
|
||||
console.log('Received SIGINT, shutting down gracefully');
|
||||
logStream.end();
|
||||
server.close(() => {
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -8,32 +8,52 @@ export const getAllRecordings = async (): Promise<{
|
||||
recordings: MeetRecordingInfo[];
|
||||
}> => {
|
||||
const url = `${configService.meetApiUrl}/recordings`;
|
||||
console.log(`Fetching all recordings from: ${url}`);
|
||||
|
||||
let { pagination, recordings } = await get<{
|
||||
pagination: any;
|
||||
recordings: MeetRecordingInfo[];
|
||||
}>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
|
||||
while (pagination.isTruncated) {
|
||||
const nextPageUrl = `${url}?nextPageToken=${pagination.nextPageToken}`;
|
||||
const nextPageResult = await get<{
|
||||
try {
|
||||
let { pagination, recordings } = await get<{
|
||||
pagination: any;
|
||||
recordings: MeetRecordingInfo[];
|
||||
}>(nextPageUrl, {
|
||||
}>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
recordings.push(...nextPageResult.recordings);
|
||||
pagination = nextPageResult.pagination;
|
||||
}
|
||||
|
||||
return { pagination, recordings };
|
||||
console.log(`Fetched initial page with ${recordings.length} recordings, isTruncated: ${pagination.isTruncated}`);
|
||||
|
||||
while (pagination.isTruncated) {
|
||||
const nextPageUrl = `${url}?nextPageToken=${pagination.nextPageToken}`;
|
||||
console.log(`Fetching next page from: ${nextPageUrl}`);
|
||||
const nextPageResult = await get<{
|
||||
pagination: any;
|
||||
recordings: MeetRecordingInfo[];
|
||||
}>(nextPageUrl, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
recordings.push(...nextPageResult.recordings);
|
||||
pagination = nextPageResult.pagination;
|
||||
console.log(`Fetched additional ${nextPageResult.recordings.length} recordings, total: ${recordings.length}`);
|
||||
}
|
||||
|
||||
console.log(`Successfully fetched total of ${recordings.length} recordings`);
|
||||
return { pagination, recordings };
|
||||
} catch (error) {
|
||||
console.error('Error fetching all recordings:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteAllRecordings = async (recordingIds: string[]): Promise<void> => {
|
||||
const url = `${configService.meetApiUrl}/recordings?recordingIds=${recordingIds.join(',')}`;
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Deleting ${recordingIds.length} recordings from: ${url}`);
|
||||
console.log('Recording IDs to delete:', recordingIds);
|
||||
try {
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Successfully deleted ${recordingIds.length} recordings`);
|
||||
} catch (error) {
|
||||
console.error(`Error deleting ${recordingIds.length} recordings:`, error);
|
||||
console.error('Recording IDs that failed:', recordingIds);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -8,9 +8,17 @@ export async function getAllRooms(): Promise<{
|
||||
rooms: MeetRoom[];
|
||||
}> {
|
||||
const url = `${configService.meetApiUrl}/rooms`;
|
||||
return get<{ pagination: any; rooms: MeetRoom[] }>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Fetching all rooms from: ${url}`);
|
||||
try {
|
||||
const result = await get<{ pagination: any; rooms: MeetRoom[] }>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Successfully fetched ${result.rooms.length} rooms`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error fetching all rooms:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function createRoom(roomData: MeetRoomOptions): Promise<MeetRoom> {
|
||||
@ -23,23 +31,48 @@ export async function createRoom(roomData: MeetRoomOptions): Promise<MeetRoom> {
|
||||
roomData.autoDeletionDate = new Date(roomData.autoDeletionDate).getTime();
|
||||
}
|
||||
|
||||
console.log('Creating room with options:', roomData);
|
||||
return post<MeetRoom>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey },
|
||||
body: roomData
|
||||
});
|
||||
console.log('Creating room with options:', JSON.stringify(roomData, null, 2));
|
||||
console.log(`Making POST request to: ${url}`);
|
||||
try {
|
||||
const result = await post<MeetRoom>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey },
|
||||
body: roomData
|
||||
});
|
||||
console.log('Room created successfully:', JSON.stringify(result, null, 2));
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error creating room:', error);
|
||||
console.error('Room data that failed:', JSON.stringify(roomData, null, 2));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteRoom(roomId: string): Promise<void> {
|
||||
const url = `${configService.meetApiUrl}/rooms/${roomId}`;
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Deleting room ${roomId} from: ${url}`);
|
||||
try {
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Room ${roomId} deleted successfully`);
|
||||
} catch (error) {
|
||||
console.error(`Error deleting room ${roomId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteAllRooms(roomIds: string[]): Promise<void> {
|
||||
const url = `${configService.meetApiUrl}/rooms?roomIds=${roomIds.join(',')}`;
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Deleting ${roomIds.length} rooms from: ${url}`);
|
||||
console.log('Room IDs to delete:', roomIds);
|
||||
try {
|
||||
await del<void>(url, {
|
||||
headers: { 'x-api-key': configService.meetApiKey }
|
||||
});
|
||||
console.log(`Successfully deleted ${roomIds.length} rooms`);
|
||||
} catch (error) {
|
||||
console.error(`Error deleting ${roomIds.length} rooms:`, error);
|
||||
console.error('Room IDs that failed:', roomIds);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,19 +18,38 @@ async function request<T>(method: string, url: string, options: RequestOptions =
|
||||
body: options.body ? JSON.stringify(options.body) : undefined
|
||||
};
|
||||
|
||||
const response = await fetch(fullUrl, fetchOptions);
|
||||
if (!response.ok) {
|
||||
console.log(`Making ${method} request to: ${fullUrl}`);
|
||||
console.log('Request headers:', fetchOptions.headers);
|
||||
|
||||
try {
|
||||
const response = await fetch(fullUrl, fetchOptions);
|
||||
|
||||
console.log(`Response status: ${response.status} ${response.statusText}`);
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
console.error(`HTTP Error ${response.status}:`, text);
|
||||
throw new Error(`HTTP ${response.status} (${response.statusText}): ${text || 'No response body'}`);
|
||||
}
|
||||
|
||||
// Handle empty responses (e.g., for DELETE requests)
|
||||
const text = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${text}`);
|
||||
}
|
||||
if (!text) {
|
||||
console.log('Empty response received');
|
||||
return {} as T;
|
||||
}
|
||||
|
||||
// Handle empty responses (e.g., for DELETE requests)
|
||||
const text = await response.text();
|
||||
if (!text) {
|
||||
return {} as T;
|
||||
}
|
||||
console.log('Response received successfully');
|
||||
return JSON.parse(text) as T;
|
||||
} catch (error) {
|
||||
console.error(`Request failed for ${method} ${fullUrl}:`, error);
|
||||
|
||||
return JSON.parse(text) as T;
|
||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||
throw new Error(`Network error: Unable to connect to ${fullUrl}. Check if the service is running.`);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function get<T>(url: string, options?: Omit<RequestOptions, 'body'>): Promise<T> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user