Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds a Vercel rewrite for /api/* calls and hardens the frontend API client to surface readable errors when the backend/proxy returns non-JSON responses.
Changes:
- Added
vercel.jsonrewrite to proxy/api/(.*)to the VPS API endpoint. - Introduced
readPayload()injobsServiceto gracefully read JSON or text payloads. - Added a unit test covering non-JSON error responses for
fetchKeywords().
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
vercel.json |
Adds a Vercel rewrite to forward /api/* requests to the backend host. |
frontend/src/services/jobsService.ts |
Centralizes response parsing to support non-JSON bodies and improve thrown error messages. |
frontend/tests/unit/utils/jobsService.test.ts |
Adds coverage for non-JSON error payloads from the API/proxy layer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!contentType || contentType.includes("application/json")) { | ||
| try { | ||
| const payload = await response.json(); | ||
| return payload && typeof payload === "object" ? (payload as Record<string, unknown>) : {}; | ||
| } catch { | ||
| // Fallback below for non-JSON bodies returned by proxies/platforms. | ||
| } | ||
| } | ||
|
|
||
| if (typeof response.text === "function") { | ||
| const text = await response.text(); | ||
| return text ? { message: text } : {}; | ||
| } | ||
|
|
||
| return {}; |
There was a problem hiding this comment.
readPayload tenta fazer response.json() quando o content-type está vazio e, se o parse falhar, faz fallback para response.text(). Em fetch, ler o body via json() consome o stream; após uma exceção de parse normalmente não é possível ler o body novamente, então o fallback tende a não funcionar. Sugestão: ler o body uma única vez via text() e então fazer JSON.parse quando apropriado, ou usar response.clone() antes de tentar json() para preservar o body para o fallback.
| if (!contentType || contentType.includes("application/json")) { | |
| try { | |
| const payload = await response.json(); | |
| return payload && typeof payload === "object" ? (payload as Record<string, unknown>) : {}; | |
| } catch { | |
| // Fallback below for non-JSON bodies returned by proxies/platforms. | |
| } | |
| } | |
| if (typeof response.text === "function") { | |
| const text = await response.text(); | |
| return text ? { message: text } : {}; | |
| } | |
| return {}; | |
| if (typeof response.text !== "function") { | |
| return {}; | |
| } | |
| const text = await response.text(); | |
| if (!text) { | |
| return {}; | |
| } | |
| if (!contentType || contentType.includes("application/json")) { | |
| try { | |
| const payload = JSON.parse(text); | |
| return payload && typeof payload === "object" ? (payload as Record<string, unknown>) : {}; | |
| } catch { | |
| // Fallback below for non-JSON bodies returned by proxies/platforms. | |
| } | |
| } | |
| return { message: text }; |
| "rewrites": [ | ||
| { | ||
| "source": "/api/(.*)", | ||
| "destination": "http://jobsglobalscraper.ddns.net/api/$1" |
There was a problem hiding this comment.
O rewrite está apontando para um destino http:// (sem TLS). Isso expõe tráfego em texto claro entre a infraestrutura da Vercel e o backend; se o backend suporta HTTPS, prefira https://... (ou outra solução de proxy seguro).
| "destination": "http://jobsglobalscraper.ddns.net/api/$1" | |
| "destination": "https://jobsglobalscraper.ddns.net/api/$1" |
| { | ||
| "rewrites": [ | ||
| { | ||
| "source": "/api/(.*)", | ||
| "destination": "http://jobsglobalscraper.ddns.net/api/$1" | ||
| } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Já existe um frontend/vercel.json com o mesmo conteúdo. Manter duas configs de Vercel em locais diferentes tende a causar drift/confusão sobre qual arquivo é efetivamente usado (depende do Root Directory configurado no projeto Vercel). Sugestão: consolidar em um único local e remover o duplicado, ou documentar explicitamente qual diretório é o root do deploy.
No description provided.