fix(api): distinguish domain-not-found (404) from provider failure (502) on zone endpoints

Introduce service.ErrProviderUnavailable, wrapped only around the
provider GetRecords call in ZoneRecords. handleZoneRecords and
handleTemplateFromZone now use errors.Is against it to tell a real
provider outage (502) apart from local resolution failures such as an
unknown domain (404), instead of collapsing every ZoneRecords error
into a blanket 502. Also fixes handleTemplateFromZone's GetDomain
error branch to return 404 "domain not found" instead of 500, for
consistency with handleSetDomainTemplate/handleDomainHistory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
This commit is contained in:
2026-07-05 12:14:46 +07:00
parent 9ccb304d2e
commit 5662334799
3 changed files with 53 additions and 7 deletions
+11 -3
View File
@@ -86,7 +86,11 @@ func (a *API) handleZoneRecords(w http.ResponseWriter, r *http.Request) {
recs, err := a.Svc.ZoneRecords(r.Context(), pid, did)
if err != nil {
log.Printf("api: zone records failed: %v", err)
writeErr(w, http.StatusBadGateway, "не удалось получить записи зоны у провайдера")
if errors.Is(err, service.ErrProviderUnavailable) {
writeErr(w, http.StatusBadGateway, "не удалось получить записи зоны у провайдера")
} else {
writeErr(w, http.StatusNotFound, "домен не найден")
}
return
}
doc := dto.FromModel(recs)
@@ -107,13 +111,17 @@ func (a *API) handleTemplateFromZone(w http.ResponseWriter, r *http.Request) {
dom, err := a.Store.GetDomain(r.Context(), did, pid)
if err != nil {
log.Printf("api: template-from-zone: get domain failed: %v", err)
writeErr(w, http.StatusInternalServerError, "internal error")
writeErr(w, http.StatusNotFound, "домен не найден")
return
}
recs, err := a.Svc.ZoneRecords(r.Context(), pid, did)
if err != nil {
log.Printf("api: template-from-zone: zone records failed: %v", err)
writeErr(w, http.StatusBadGateway, "не удалось получить записи зоны у провайдера")
if errors.Is(err, service.ErrProviderUnavailable) {
writeErr(w, http.StatusBadGateway, "не удалось получить записи зоны у провайдера")
} else {
writeErr(w, http.StatusNotFound, "домен не найден")
}
return
}
// Snapshot only managed records — NS/SOA are read-only and never templated.