diff --git a/Caddyfile b/Caddyfile index 0291192..7eed236 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,6 +1,10 @@ :80 { encode gzip zstd + handle_path /api/* { + reverse_proxy backend:8082 + } + handle { reverse_proxy frontend:80 } diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index eee23cc..94c12ce 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -4,7 +4,6 @@ services: restart: unless-stopped ports: - "127.0.0.1:${CADDY_HTTP_PORT:-8088}:80" - - "127.0.0.1:${CADDY_HTTPS_PORT:-8443}:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 6170b75..77c0880 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -30,6 +30,16 @@ export class ApiError extends Error { } } +export function getApiErrorMessage(error: unknown) { + if (error instanceof ApiError) { + return "Erro " + error.status + ": " + error.message; + } + if (error instanceof Error) { + return error.message; + } + return "Falha na comunicação com a API"; +} + async function apiRequest(path: string, options: RequestOptions = {}): Promise { const url = buildApiUrl(path); Object.entries(options.params ?? {}).forEach(([key, value]) => { @@ -51,7 +61,7 @@ async function apiRequest(path: string, options: RequestOptions = {}): Promis setAuthToken(null); } if (!response.ok) { - const detail = await response.text(); + const detail = await readErrorMessage(response); throw new ApiError(detail || "Falha na comunicação com a API", response.status); } if (response.status === 204) { @@ -60,6 +70,23 @@ async function apiRequest(path: string, options: RequestOptions = {}): Promis return response.json() as Promise; } +async function readErrorMessage(response: Response) { + const contentType = response.headers.get("Content-Type") ?? ""; + const text = await response.text(); + if (!text) { + return response.statusText; + } + if (contentType.includes("application/json")) { + try { + const json = JSON.parse(text) as { message?: string; detail?: string; error?: string; title?: string }; + return json.message ?? json.detail ?? json.error ?? json.title ?? text; + } catch { + return text; + } + } + return text; +} + function buildApiUrl(path: string) { if (API_BASE_URL.startsWith("http://") || API_BASE_URL.startsWith("https://")) { return new URL(path, API_BASE_URL); diff --git a/frontend/src/pages/NovaBuscaPage.tsx b/frontend/src/pages/NovaBuscaPage.tsx index fed33b0..0b6e99a 100644 --- a/frontend/src/pages/NovaBuscaPage.tsx +++ b/frontend/src/pages/NovaBuscaPage.tsx @@ -6,7 +6,7 @@ import { Button } from "../components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card"; import { Input } from "../components/ui/input"; import { Select } from "../components/ui/select"; -import { api } from "../lib/api"; +import { api, getApiErrorMessage } from "../lib/api"; export function NovaBuscaPage() { const navigate = useNavigate(); @@ -93,7 +93,7 @@ export function NovaBuscaPage() { {formError &&

{formError}

} {criarBusca.isError && (

- Não foi possível criar a busca. Atualize a página e tente novamente. + Não foi possível criar a busca. {getApiErrorMessage(criarBusca.error)}

)}