import axios, { AxiosResponse } from 'axios'; export async function storeData( servers: string[], key: string, value: Blob, ttl: number | null ): Promise { for (const server of servers) { try { // Handle relative paths (for development proxy) vs absolute URLs (for production) let url: string; if (server.startsWith('/')) { // Relative path - construct manually for proxy url = `${server}/store/${encodeURIComponent(key)}`; if (ttl !== null) { url += `?ttl=${ttl}`; } } else { // Absolute URL - use URL constructor const urlObj = new URL(`${server}/store/${encodeURIComponent(key)}`); if (ttl !== null) { urlObj.searchParams.append('ttl', ttl.toString()); } url = urlObj.toString(); } // Test first that data is not already stored const testResponse = await testData(url, key); if (testResponse) { console.log('Data already stored:', key); continue; } else { console.log('Data not stored for server:', key, server); } // Send the encrypted ArrayBuffer as the raw request body. const response = await axios.post(url, value, { headers: { 'Content-Type': 'application/octet-stream', }, }); console.log('Data stored successfully:', key); if (response.status !== 200) { console.error('Received response status', response.status); continue; } return response; } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 409) { return null; } console.error('Error storing data:', error); } } return null; } export async function retrieveData(servers: string[], key: string): Promise { for (const server of servers) { try { // Handle relative paths (for development proxy) vs absolute URLs (for production) const url = server.startsWith('/') ? `${server}/retrieve/${key}` // Relative path - use as-is for proxy : new URL(`${server}/retrieve/${key}`).toString(); // Absolute URL - construct properly console.log('Retrieving data', key, ' from:', url); // When fetching the data from the server: const response = await axios.get(url, { responseType: 'arraybuffer', }); if (response.status === 200) { // Validate that we received an ArrayBuffer if (response.data instanceof ArrayBuffer) { return response.data; } else { console.error('Server returned non-ArrayBuffer data:', typeof response.data); continue; } } else { console.error(`Server ${server} returned status ${response.status}`); continue; } } catch (error) { if (axios.isAxiosError(error)) { if (error.response?.status === 404) { console.log(`Data not found on server ${server} for key ${key}`); continue; // Try next server } else if (error.response?.status) { console.error( `Server ${server} error ${error.response.status}:`, error.response.statusText ); continue; } else { console.error(`Network error connecting to ${server}:`, (error as Error).message); continue; } } else { console.error(`Unexpected error retrieving data from ${server}:`, error); continue; } } } return null; } export async function testData(url: string, _key: string): Promise { try { const response = await axios.get(url); if (response.status !== 200) { console.error(`Test response status: ${response.status}`); return false; } return true; } catch (error) { console.error('Error testing data:', error); return null; } }