Files
MikrotikManager/shared/api/system-database.ts
T
Denozordec 158fc36294
Docker images / prepare-release (push) Successful in 6s
Docker images / backend-image (push) Successful in 1m36s
Docker images / frontend-image (push) Successful in 1m40s
Docker images / updater-image (push) Successful in 38s
Docker images / notify-webhook (push) Has been skipped
Docker images / publish-release (push) Successful in 6s
fix(api): увеличить лимит размера тела запроса и улучшить обработку URL для API
2026-05-12 23:11:23 +07:00

77 lines
2.5 KiB
TypeScript

import { ApiClientError } from "@/shared/api/http-client"
import { configuredBackendUrl } from "@/lib/backend-url"
const MAX_RESTORE_BYTES = 512 * 1024 * 1024
function trimBaseUrl(baseUrl: string): string {
return baseUrl.replace(/\/$/, "")
}
function resolveDatabaseApiUrl(baseUrl: string, path: string): string {
if (configuredBackendUrl().kind === "same-origin") {
return path
}
return `${trimBaseUrl(baseUrl)}${path}`
}
function parseFilename(contentDisposition: string | null, fallback: string): string {
if (!contentDisposition) return fallback
const utfMatch = /filename\*=UTF-8''([^;]+)/i.exec(contentDisposition)
if (utfMatch?.[1]) {
try {
return decodeURIComponent(utfMatch[1])
} catch {
return utfMatch[1]
}
}
const plainMatch = /filename="([^"]+)"/i.exec(contentDisposition)
if (plainMatch?.[1]) return plainMatch[1]
return fallback
}
export async function downloadSystemDatabaseBackup(
baseUrl: string,
): Promise<{ blob: Blob; filename: string }> {
const res = await fetch(resolveDatabaseApiUrl(baseUrl, "/api/system/database/backup"))
if (!res.ok) {
const payload = await res.json().catch(() => undefined)
const msg =
typeof payload === "object" &&
payload !== null &&
"error" in payload &&
typeof (payload as { error?: unknown }).error === "string"
? (payload as { error: string }).error
: res.statusText
throw new ApiClientError(msg, res.status, payload)
}
const blob = await res.blob()
const filename = parseFilename(res.headers.get("Content-Disposition"), "mikrotik-manager.db")
return { blob, filename }
}
export async function restoreSystemDatabaseBackup(baseUrl: string, file: File): Promise<void> {
if (file.size > MAX_RESTORE_BYTES) {
throw new ApiClientError(
`Файл больше ${MAX_RESTORE_BYTES / (1024 * 1024)} МБ — уменьшите бэкап или обратитесь к администратору`,
413,
)
}
const body = await file.arrayBuffer()
const res = await fetch(resolveDatabaseApiUrl(baseUrl, "/api/system/database/restore"), {
method: "POST",
headers: { "Content-Type": "application/octet-stream" },
body,
})
if (!res.ok) {
const payload = await res.json().catch(() => undefined)
const msg =
typeof payload === "object" &&
payload !== null &&
"error" in payload &&
typeof (payload as { error?: unknown }).error === "string"
? (payload as { error: string }).error
: res.statusText
throw new ApiClientError(msg, res.status, payload)
}
}