* Builds an error from a non-success API response. * * Apple documents error responses as JSON containing `errorCode` and `errorMessage`, but an * actual infrastructure failure can still return a non-JSON body (e.g. an HTML 5xx page, or an * empty body). The body is therefore parsed defe
(result: Response, retryAfter?: number)
| 247 | * the raw body rather than throwing an opaque JSON parse error. |
| 248 | */ |
| 249 | private async errorForResponse(result: Response, retryAfter?: number): Promise<Error> { |
| 250 | const text = await result.text() |
| 251 | |
| 252 | let parsed: unknown |
| 253 | try { |
| 254 | parsed = JSON.parse(text) |
| 255 | } catch { |
| 256 | parsed = undefined |
| 257 | } |
| 258 | |
| 259 | if ( |
| 260 | typeof parsed === "object" && |
| 261 | parsed !== null && |
| 262 | "errorCode" in parsed && |
| 263 | typeof parsed.errorCode === "number" && |
| 264 | "errorMessage" in parsed && |
| 265 | typeof parsed.errorMessage === "string" |
| 266 | ) { |
| 267 | return new AppStoreError(parsed.errorCode, parsed.errorMessage, retryAfter) |
| 268 | } |
| 269 | |
| 270 | const body = text.trim() |
| 271 | const snippet = body.length > 500 ? `${body.slice(0, 500)}…` : body |
| 272 | const detail = snippet.length > 0 ? `: ${snippet}` : "" |
| 273 | return new Error(`The App Store Server API returned an unexpected response (HTTP ${result.status})${detail}`) |
| 274 | } |
| 275 | |
| 276 | /** |
| 277 | * Returns an existing authentication token (if its still valid) or generates a new one. |