function toHeadersObject(headers?: HeadersInit): Record { if (!headers) { return {} } if (headers instanceof Headers) { return Object.fromEntries(headers.entries()) } if (Array.isArray(headers)) { return Object.fromEntries(headers) } return { ...headers } } function getDownloadFileName(contentDisposition: string | null, fallback: string) { if (!contentDisposition) { return fallback } const utf8Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i) if (utf8Match?.[1]) { return decodeURIComponent(utf8Match[1]) } const asciiMatch = contentDisposition.match(/filename="([^"]+)"/i) if (asciiMatch?.[1]) { return asciiMatch[1] } return fallback } export function useApiAuthHeader() { const runtimeConfig = useRuntimeConfig() const token = runtimeConfig.public.apiSecretKey if (!token) { return {} } // Tous les appels frontend vers /api/* reutilisent ce header commun. return { Authorization: `Bearer ${token}` } } export const apiFetch = $fetch.create({}) export function apiRequest(input: RequestInfo | URL, init: RequestInit = {}) { return fetch(input, withApiAuth(init)) } export async function downloadApiFile(url: string, fileNameFallback: string) { // Les telechargements passent aussi par fetch pour pouvoir recuperer // le contenu et le nom de fichier renvoye par l'API. const response = await apiRequest(url) if (!response.ok) { throw new Error(`HTTP ${response.status}`) } const blob = await response.blob() const objectUrl = URL.createObjectURL(blob) const fileName = getDownloadFileName( response.headers.get("content-disposition"), fileNameFallback ) const link = document.createElement("a") link.href = objectUrl link.download = fileName link.style.display = "none" document.body.appendChild(link) link.click() link.remove() URL.revokeObjectURL(objectUrl) } export function withApiAuth(init: RequestInit = {}) { // Fusionne le header d'auth avec d'eventuels headers deja fournis. return { ...init, headers: { ...useApiAuthHeader(), ...toHeadersObject(init.headers) } } }