fix(api): support xsrf and backend error message
This commit is contained in:
+30
-1
@@ -17,6 +17,22 @@ async function readJsonBody(res: Response): Promise<unknown | null> {
|
||||
}
|
||||
}
|
||||
|
||||
function getCookieValue(name: string): string | null {
|
||||
if (typeof document === "undefined") return null
|
||||
if (!document.cookie) return null
|
||||
|
||||
for (const part of document.cookie.split("; ")) {
|
||||
if (part.startsWith(`${name}=`)) return part.slice(name.length + 1)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function isApiErrorWithMessage(value: unknown): value is { code: number; message: string } {
|
||||
if (typeof value !== "object" || value === null) return false
|
||||
const v = value as { code?: unknown; message?: unknown }
|
||||
return typeof v.code === "number" && typeof v.message === "string"
|
||||
}
|
||||
|
||||
export async function httpJson<T>(path: string, init?: JsonRequestInit): Promise<T> {
|
||||
if (/^https?:\/\//.test(path)) {
|
||||
throw new Error("Absolute URLs are not allowed")
|
||||
@@ -33,6 +49,15 @@ export async function httpJson<T>(path: string, init?: JsonRequestInit): Promise
|
||||
headers.set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
const method = (rest.method ?? "GET").toUpperCase()
|
||||
if (
|
||||
(method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE") &&
|
||||
!headers.has("XSRF-TOKEN")
|
||||
) {
|
||||
const xsrfToken = getCookieValue("__Host-XSRF-TOKEN")
|
||||
if (xsrfToken) headers.set("XSRF-TOKEN", xsrfToken)
|
||||
}
|
||||
|
||||
const res = await fetch(path, {
|
||||
...rest,
|
||||
headers,
|
||||
@@ -45,7 +70,11 @@ export async function httpJson<T>(path: string, init?: JsonRequestInit): Promise
|
||||
return data as T
|
||||
}
|
||||
|
||||
const apiError = isApiError(data) ? data : null
|
||||
const apiError: ApiError | null = isApiError(data)
|
||||
? data
|
||||
: isApiErrorWithMessage(data)
|
||||
? { code: data.code, msg: data.message }
|
||||
: null
|
||||
if (res.status === 401 || apiError?.code === 401) {
|
||||
throw new Error("UNAUTHORIZED")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user