platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
62
selective-vpn-web/src/shared/api/http.ts
Normal file
62
selective-vpn-web/src/shared/api/http.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { env } from '../config/env'
|
||||
|
||||
type RequestJsonOptions = Omit<RequestInit, 'body'> & {
|
||||
timeoutMs?: number
|
||||
body?: unknown
|
||||
}
|
||||
|
||||
export class HttpError extends Error {
|
||||
public readonly status: number
|
||||
public readonly payload: string
|
||||
|
||||
constructor(message: string, status: number, payload: string) {
|
||||
super(message)
|
||||
this.status = status
|
||||
this.payload = payload
|
||||
}
|
||||
}
|
||||
|
||||
export function apiUrl(path: string): string {
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
if (!env.apiBaseUrl) {
|
||||
return normalizedPath
|
||||
}
|
||||
return `${env.apiBaseUrl}${normalizedPath}`
|
||||
}
|
||||
|
||||
export async function requestJson<T>(path: string, options: RequestJsonOptions = {}): Promise<T> {
|
||||
const controller = new AbortController()
|
||||
const timeoutMs = options.timeoutMs ?? 8000
|
||||
|
||||
const headers = new Headers(options.headers || {})
|
||||
const hasBody = options.body !== undefined
|
||||
if (hasBody && !headers.has('Content-Type')) {
|
||||
headers.set('Content-Type', 'application/json')
|
||||
}
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort()
|
||||
}, timeoutMs)
|
||||
|
||||
try {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
...options,
|
||||
headers,
|
||||
body: hasBody ? JSON.stringify(options.body) : undefined,
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
const text = await response.text()
|
||||
if (!response.ok) {
|
||||
throw new HttpError(`Request failed: ${response.status}`, response.status, text)
|
||||
}
|
||||
|
||||
if (!text) {
|
||||
return {} as T
|
||||
}
|
||||
|
||||
return JSON.parse(text) as T
|
||||
} finally {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user