diff options
| author | ivarlovlie <git@ivarlovlie.no> | 2022-12-09 03:57:12 +0100 |
|---|---|---|
| committer | ivarlovlie <git@ivarlovlie.no> | 2022-12-09 03:57:12 +0100 |
| commit | 4dbef3fcd7a14437d55c555cf10d50de8e50d7d1 (patch) | |
| tree | 632589ecfcfb4dfddeafb71d0077257584b5e7ec /code/app/src/api/_fetch.ts | |
| parent | 914c75e0ceeb3e11ddd55e94bb461c26b0db5b7a (diff) | |
| download | greatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.tar.xz greatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.zip | |
feat: Move everything out of $lib
Diffstat (limited to 'code/app/src/api/_fetch.ts')
| -rw-r--r-- | code/app/src/api/_fetch.ts | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/code/app/src/api/_fetch.ts b/code/app/src/api/_fetch.ts new file mode 100644 index 0000000..370b071 --- /dev/null +++ b/code/app/src/api/_fetch.ts @@ -0,0 +1,94 @@ +import {Temporal} from "temporal-polyfill"; +import {redirect} from "@sveltejs/kit"; +import {browser} from "$app/environment"; +import {goto} from "$app/navigation"; +import {SignInPageMessage, signInPageMessageQueryKey} from "$routes/(main)/(public)/sign-in"; +import {log_error} from "$help/logger"; + +export async function http_post_async(url: string, body?: object | string, timeout = -1, skip_401_check = false, abort_signal?: AbortSignal): Promise<Response> { + const init = make_request_init("post", body, abort_signal); + const response = await internal_fetch_async({url, init, timeout}); + if (!skip_401_check && await redirect_if_401_async(response)) throw new Error("Server returned 401"); + return response; +} + +export async function http_get_async(url: string, timeout = -1, skip_401_check = false, abort_signal?: AbortSignal): Promise<Response> { + const init = make_request_init("get", undefined, abort_signal); + const response = await internal_fetch_async({url, init, timeout}); + if (!skip_401_check && await redirect_if_401_async(response)) throw new Error("Server returned 401"); + return response; +} + +export async function http_delete_async(url: string, body?: object | string, timeout = -1, skip_401_check = false, abort_signal?: AbortSignal): Promise<Response> { + const init = make_request_init("delete", body, abort_signal); + const response = await internal_fetch_async({url, init, timeout}); + if (!skip_401_check && await redirect_if_401_async(response)) throw new Error("Server returned 401"); + return response; +} + +async function internal_fetch_async(request: InternalFetchRequest): Promise<Response> { + if (!request.init) throw new Error("request.init is required"); + const fetch_request = new Request(request.url, request.init); + let response: any; + + try { + if (request.timeout && request.timeout > 500) { + response = await Promise.race([ + fetch(fetch_request), + new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), request.timeout)), + ]); + } else { + response = await fetch(fetch_request); + } + } catch (error: any) { + log_error(error); + if (error.message === "Timeout") { + console.error("Request timed out"); + } else if (error.message === "Network request failed") { + console.error("No internet connection"); + } else { + throw error; + } + } + + return response; +} + +async function redirect_if_401_async(response: Response): Promise<boolean> { + if (response.status === 401) { + const redirectUrl = `/sign-in?${signInPageMessageQueryKey}=${SignInPageMessage.LOGGED_OUT}`; + clear_session_data(); + if (browser) { + await goto(redirectUrl); + } else { + throw redirect(307, redirectUrl); + } + } + return false; +} + +function make_request_init(method: string, body?: any, signal?: AbortSignal): RequestInit { + const init = { + method, + credentials: "include", + signal, + headers: { + "X-TimeZone": Temporal.Now.timeZone().id, + }, + } as RequestInit; + + if (body) { + init.body = JSON.stringify(body); + init.headers["Content-Type"] = "application/json;charset=UTF-8"; + } + + return init; +} + + +export type InternalFetchRequest = { + url: string, + init: RequestInit, + timeout?: number + retry_count?: number, +}
\ No newline at end of file |
