handle backend errors
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 10s
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 10s
This commit is contained in:
@@ -188,7 +188,7 @@ export default function SignUpForm() {
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Atolls</SelectLabel>
|
||||
{atolls?.data.map((atoll) => (
|
||||
{(atolls?.data ?? []).map((atoll) => (
|
||||
<SelectItem key={atoll.id} value={atoll.id.toString()}>
|
||||
{atoll.name}
|
||||
</SelectItem>
|
||||
|
||||
@@ -29,6 +29,25 @@ apiClient.interceptors.request.use((config) => {
|
||||
return config;
|
||||
});
|
||||
|
||||
// Normalise non-JSON error pages. Django (DisallowedHost / DEBUG tracebacks),
|
||||
// nginx (502/504), etc. return an HTML body on 4xx/5xx instead of the JSON
|
||||
// envelope callers expect. Left as-is, the raw HTML string flows into consumers
|
||||
// and crashes things like `atolls.data.map(...)`. Rewrite it into a JSON error
|
||||
// body so `handleApiResponse` and action code read a clean `{ message, detail }`.
|
||||
apiClient.interceptors.response.use((response) => {
|
||||
const contentType = String(response.headers?.["content-type"] ?? "");
|
||||
const isHtml = !contentType.includes("application/json");
|
||||
if (response.status >= 400 && isHtml && typeof response.data === "string") {
|
||||
const title = response.data.match(/<title>([\s\S]*?)<\/title>/i)?.[1]?.trim();
|
||||
response.data = {
|
||||
message: `Server error (${response.status})`,
|
||||
detail:
|
||||
title || `The server returned a non-JSON ${response.status} response.`,
|
||||
};
|
||||
}
|
||||
return response;
|
||||
});
|
||||
|
||||
// On 401 the token is dead — clear it and bounce to signin (once).
|
||||
apiClient.interceptors.response.use((response) => {
|
||||
if (response.status === 401) {
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import type { ApiResponse, Atoll } from "@/lib/backend-types";
|
||||
import apiClient from "@/lib/api-client";
|
||||
import { handleApiResponse } from "@/utils/tryCatch";
|
||||
|
||||
/**
|
||||
* Atoll list (with nested islands) for the signup atoll/island dropdowns.
|
||||
* The endpoint is paginated, so this returns the `{ meta, links, data }`
|
||||
* envelope — consumers read `.data`.
|
||||
*
|
||||
* Runs through `handleApiResponse` so a 4xx/5xx (e.g. DisallowedHost 400)
|
||||
* throws a clean error for React Query to surface, instead of returning a
|
||||
* non-envelope body that crashes `atolls.data.map(...)`.
|
||||
*/
|
||||
export async function getAtolls() {
|
||||
const response = await apiClient.get("/api/auth/atolls/");
|
||||
return response.data as ApiResponse<Atoll>;
|
||||
return handleApiResponse<ApiResponse<Atoll>>(response, "getAtolls");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user