fix(cdn): resolve a pull zone when the API answers with a bare array #178

Merged
pat-s merged 1 commit from fix/purge-zone-lookup into main 2026-08-31 09:55:38 +00:00
Showing only changes of commit 6b5d7d16c5 - Show all commits

fix(cdn): resolve a pull zone when the API answers with a bare array

The zone lookup used `.Items // .` to accept both response shapes. It
accepts neither: indexing an array with a string is an error in jq, not a
null, so `//` never substitutes and the whole expression aborts with
"Cannot index array with string".

The listing endpoint answers with a bare array for this account, so every
purge of cran.allianceswisspass.devxy.io has been failing. Reindex
pipelines reported failure at the purge step while the reindex itself had
succeeded, and that zone kept serving objects the rebuild replaced.

Also surfaced by the same failure:

- The listing response was used without checking the HTTP status, so an
  auth or rate-limit error was reported as a missing hostname.
- A hostname matching several zones silently purged only the first.

Verified against stubbed array-shaped and object-shaped responses; the
previous script fails the array case.
Patrick Schratz 2026-08-31 09:07:41 +00:00
No known key found for this signature in database
GPG key ID: 62050D5BC68AB6DC

View file

@ -47,12 +47,31 @@ resolve_zone_id() {
fi
response_file=$(mktemp)
curl -sS -o "${response_file}" \
-H "AccessKey: ${api_key}" \
"https://api.bunny.net/pullzone"
local status
status=$(
curl -sS -o "${response_file}" -w '%{http_code}' \
-H "AccessKey: ${api_key}" \
"https://api.bunny.net/pullzone?perPage=1000"
)
if [[ "${status}" != "200" ]]; then
echo "Listing BunnyCDN pull zones failed with HTTP ${status}:" >&2
head -c 500 "${response_file}" >&2
echo >&2
rm -f "${response_file}"
exit 1
fi
# The endpoint answers with a bare array on some accounts and a paginated
# object on others. `.Items // .` looks like it covers both but does not:
# indexing an array with a string is an *error*, and `//` only substitutes
# for null, so the array case aborted with
# "Cannot index array with string" and the zone was never purged.
zone_id=$(
jq -r --arg hostname "${zone}" \
'(.Items // .)[] | select(any(.Hostnames[]?; .Value == $hostname)) | .Id' \
'(if type == "object" then (.Items // []) else . end)[]
| select(any(.Hostnames[]?; .Value == $hostname))
| .Id' \
"${response_file}"
)
rm -f "${response_file}"
@ -62,6 +81,12 @@ resolve_zone_id() {
exit 1
fi
# Two zones sharing a hostname would purge only whichever jq emitted first.
if [[ $(wc -l <<<"${zone_id}") -gt 1 ]]; then
echo "Hostname ${zone} matched multiple pull zones: ${zone_id//$'\n'/ }" >&2
exit 1
fi
echo "${zone_id}"
}