Charlie PHP Expert - Volume 11A | 1 CHARLIE PHP EXPERT Volume 11A - Remedial Supplement Browser fetch(), HTTP Response, JSON Parsing & Failure Boundaries Purpose: Correct a repeated training gap found during Volume 11 certification. Charlie must distinguish three different browser-side failure classes: transport/network failure, HTTP 4xx/5xx response, and JSON parsing failure. Relationship to Volume 11: This supplement reinforces the Volume 11 objectives around Fetch/JSON/HTTP integration, async failure handling, browser/server contract debugging, security boundaries, and evidence-based troubleshooting. It supplements Volume 11; it does not replace it. 1. The Three Failure Boundaries Boundary A - Transport/network: fetch() fails before a usable HTTP Response is obtained. Examples include some DNS, connection, or browser-level network failures. In this case, await fetch(...) rejects. Boundary B - HTTP status: The browser receives a valid HTTP Response, but its status is 4xx or 5xx. Browser fetch() generally resolves with a Response object; it does not reject solely because the HTTP status is an error. Application code must inspect response.ok or response.status. Boundary C - Body/JSON parsing: A Response exists, but parsing the body as JSON fails. This occurs when await response.json() cannot parse the response body as valid JSON. 2. Why One Big catch Block Is Not Enough One outer try/catch can catch multiple failure classes, but if the code labels every caught error as the same thing, it loses diagnostic precision. The fix is not necessarily multiple top-level catches; the fix is to preserve which operation failed. 3. Important Browser-Side Rule Do not use error instanceof TypeError as a universal test for 'invalid JSON.' A browser-side fetch network failure may also surface as a TypeError. Likewise, do not assume Node.js-specific error codes such as ECONNRESET or ECONNABORTED are the portable browser mechanism unless the environment specifically provides them. 4. Correct async/await Structure A reliable structure separates the stages explicitly: first obtain the Response, then classify the HTTP status, then parse the body. That makes the evidence trail clear: did we fail before a Response existed, did the server return an error status, or did the body violate the JSON contract? Reference Implementation async function requestJson(url, options = {}) { let response; // A. Transport/network boundary try { response = await fetch(url, options); } catch (error) { return { ok: false, kind: "network", message: "Request could not obtain an HTTP response.", cause: error }; } // B. HTTP-status boundary Charlie PHP Expert - Volume 11A | 2 if (!response.ok) { let errorBody = null; try { errorBody = await response.text(); } catch (_) { // Body reading failure is secondary here. } return { ok: false, kind: "http", status: response.status, statusText: response.statusText, body: errorBody }; } // C. JSON-parse boundary try { const data = await response.json(); return { ok: true, kind: "success", status: response.status, data }; } catch (error) { return { ok: false, kind: "json", status: response.status, message: "HTTP response body was not valid JSON.", cause: error }; } } 5. Why This Structure Works Each outcome corresponds to evidence from a specific stage. If fetch() throws before a Response exists, classify it as network/transport. If a Response exists and response.ok is false, classify it as an HTTP-status failure. If the Response is successful but response.json() throws, classify it as a JSON-contract failure. 6. Invalid JSON Is Not the Same as 'Non-Object JSON' Valid JSON can be an object, array, string, number, boolean, or null. Therefore, typeof data !== 'object' is not a valid test for malformed JSON. Malformed JSON is detected by the parse operation failing. 7. HTTP Error Is Not a Network Error A 404, 422, or 500 proves that an HTTP response was received. That is different from a request that never produced a Response. Do not collapse these into a single 'network error.' 8. Browser Validation Does Not Replace PHP Validation Client-side validation improves user experience but cannot be trusted as a security boundary. A user can bypass or modify browser-side JavaScript. The PHP server must validate required fields, types, ranges, formats, business rules, authorization, tenant scope, and any data-integrity constraints before performing protected actions. 9. Safe DOM Handling When displaying server-provided values, avoid inserting untrusted content with unsafe HTML injection. Prefer APIs such as textContent for plain text. If HTML is genuinely required, use an appropriate sanitization strategy and understand the trust boundary. Charlie PHP Expert - Volume 11A | 3 10. API Contract Discipline The frontend and PHP endpoint should agree on status codes, content type, response shape, and error schema. For JSON endpoints, the server should return a consistent JSON contract whenever practical. The client should still handle the possibility that a proxy, server error page, or misconfiguration returns non-JSON content. Charlie PHP Expert - Volume 11A | 4 11. Broken Patterns Charlie Must Diagnose Broken Pattern A: Every failure is called invalid JSON. try { const response = await fetch(url); const data = await response.json(); } catch (error) { console.log("Invalid JSON"); } Why wrong: a network failure during fetch() also reaches the catch block. The label is unsupported unless the parse operation itself is known to have failed. Broken Pattern B: Treating HTTP 500 as fetch rejection. const response = await fetch(url); if (!response.ok) { // This means fetch() rejected. } Why wrong: the existence of response shows that fetch resolved. The application discovered the HTTP error by inspecting the Response. Broken Pattern C: Using JavaScript type to detect malformed JSON. const data = await response.json(); if (typeof data !== "object") { throw new Error("Invalid JSON"); } Why wrong: valid JSON can produce non-object values, and malformed JSON fails during parsing before data exists. Charlie PHP Expert - Volume 11A | 5 12. Certification Drills Drill Prompt Pass condition A fetch() throws before Response exists. What class? Network/transport failure. B Server returns HTTP 500 with valid JSON body. HTTP failure; fetch itself did not reject solely because of 500. C Server returns HTTP 200 with 'Error'. JSON parse failure / contract mismatch. D Why is instanceof TypeError not enough for JSON detection? Because browser fetch network failures may also surface as TypeError. E Why is typeof data !== 'object' wrong? Valid JSON can be scalar/array/null; malformed JSON is detected at parse time. F Browser validates email. Can PHP trust it? No; server must validate independently. 13. Volume 11A Certification Question Question: Write one browser-side JavaScript function using async/await that keeps these outcomes distinct: (1) network/transport failure before a Response exists, (2) HTTP 4xx/5xx after a Response exists, and (3) invalid JSON in an otherwise received Response. Then explain why error instanceof TypeError alone cannot reliably identify invalid JSON, and state what the PHP server must still validate even if the browser validates the form. Pass standard: Charlie must identify the three stages correctly, keep their failure evidence separate, stay in browser JavaScript for the client-side portion, avoid environment-specific assumptions not established by evidence, and preserve the server-side trust boundary. After this focused retest passes, repeat the original Volume 11 certification question. Charlie PHP Expert - Volume 11A | 1 CHARLIE PHP EXPERT Volume 11A - Remedial Supplement Browser fetch(), HTTP Response, JSON Parsing & Failure Boundaries Purpose: Correct a repeated training gap found during Volume 11 certification. Charlie must distinguish three different browser-side failure classes: transport/network failure, HTTP 4xx/5xx response, and JSON parsing failure. Relationship to Volume 11: This supplement reinforces the Volume 11 objectives around Fetch/JSON/HTTP integration, async failure handling, browser/server contract debugging, security boundaries, and evidence-based troubleshooting. It supplements Volume 11; it does not replace it. 1. The Three Failure Boundaries Boundary A - Transport/network: fetch() fails before a usable HTTP Response is obtained. Examples include some DNS, connection, or browser-level network failures. In this case, await fetch(...) rejects. Boundary B - HTTP status: The browser receives a valid HTTP Response, but its status is 4xx or 5xx. Browser fetch() generally resolves with a Response object; it does not reject solely because the HTTP status is an error. Application code must inspect response.ok or response.status. Boundary C - Body/JSON parsing: A Response exists, but parsing the body as JSON fails. This occurs when await response.json() cannot parse the response body as valid JSON. 2. Why One Big catch Block Is Not Enough One outer try/catch can catch multiple failure classes, but if the code labels every caught error as the same thing, it loses diagnostic precision. The fix is not necessarily multiple top-level catches; the fix is to preserve which operation failed. 3. Important Browser-Side Rule Do not use error instanceof TypeError as a universal test for 'invalid JSON.' A browser-side fetch network failure may also surface as a TypeError. Likewise, do not assume Node.js-specific error codes such as ECONNRESET or ECONNABORTED are the portable browser mechanism unless the environment specifically provides them. 4. Correct async/await Structure A reliable structure separates the stages explicitly: first obtain the Response, then classify the HTTP status, then parse the body. That makes the evidence trail clear: did we fail before a Response existed, did the server return an error status, or did the body violate the JSON contract? Reference Implementation async function requestJson(url, options = {}) { let response; // A. Transport/network boundary try { response = await fetch(url, options); } catch (error) { return { ok: false, kind: "network", message: "Request could not obtain an HTTP response.", cause: error }; } // B. HTTP-status boundary Charlie PHP Expert - Volume 11A | 2 if (!response.ok) { let errorBody = null; try { errorBody = await response.text(); } catch (_) { // Body reading failure is secondary here. } return { ok: false, kind: "http", status: response.status, statusText: response.statusText, body: errorBody }; } // C. JSON-parse boundary try { const data = await response.json(); return { ok: true, kind: "success", status: response.status, data }; } catch (error) { return { ok: false, kind: "json", status: response.status, message: "HTTP response body was not valid JSON.", cause: error }; } } 5. Why This Structure Works Each outcome corresponds to evidence from a specific stage. If fetch() throws before a Response exists, classify it as network/transport. If a Response exists and response.ok is false, classify it as an HTTP-status failure. If the Response is successful but response.json() throws, classify it as a JSON-contract failure. 6. Invalid JSON Is Not the Same as 'Non-Object JSON' Valid JSON can be an object, array, string, number, boolean, or null. Therefore, typeof data !== 'object' is not a valid test for malformed JSON. Malformed JSON is detected by the parse operation failing. 7. HTTP Error Is Not a Network Error A 404, 422, or 500 proves that an HTTP response was received. That is different from a request that never produced a Response. Do not collapse these into a single 'network error.' 8. Browser Validation Does Not Replace PHP Validation Client-side validation improves user experience but cannot be trusted as a security boundary. A user can bypass or modify browser-side JavaScript. The PHP server must validate required fields, types, ranges, formats, business rules, authorization, tenant scope, and any data-integrity constraints before performing protected actions. 9. Safe DOM Handling When displaying server-provided values, avoid inserting untrusted content with unsafe HTML injection. Prefer APIs such as textContent for plain text. If HTML is genuinely required, use an appropriate sanitization strategy and understand the trust boundary. Charlie PHP Expert - Volume 11A | 3 10. API Contract Discipline The frontend and PHP endpoint should agree on status codes, content type, response shape, and error schema. For JSON endpoints, the server should return a consistent JSON contract whenever practical. The client should still handle the possibility that a proxy, server error page, or misconfiguration returns non-JSON content. Charlie PHP Expert - Volume 11A | 4 11. Broken Patterns Charlie Must Diagnose Broken Pattern A: Every failure is called invalid JSON. try { const response = await fetch(url); const data = await response.json(); } catch (error) { console.log("Invalid JSON"); } Why wrong: a network failure during fetch() also reaches the catch block. The label is unsupported unless the parse operation itself is known to have failed. Broken Pattern B: Treating HTTP 500 as fetch rejection. const response = await fetch(url); if (!response.ok) { // This means fetch() rejected. } Why wrong: the existence of response shows that fetch resolved. The application discovered the HTTP error by inspecting the Response. Broken Pattern C: Using JavaScript type to detect malformed JSON. const data = await response.json(); if (typeof data !== "object") { throw new Error("Invalid JSON"); } Why wrong: valid JSON can produce non-object values, and malformed JSON fails during parsing before data exists. Charlie PHP Expert - Volume 11A | 5 12. Certification Drills Drill Prompt Pass condition A fetch() throws before Response exists. What class? Network/transport failure. B Server returns HTTP 500 with valid JSON body. HTTP failure; fetch itself did not reject solely because of 500. C Server returns HTTP 200 with 'Error'. JSON parse failure / contract mismatch. D Why is instanceof TypeError not enough for JSON detection? Because browser fetch network failures may also surface as TypeError. E Why is typeof data !== 'object' wrong? Valid JSON can be scalar/array/null; malformed JSON is detected at parse time. F Browser validates email. Can PHP trust it? No; server must validate independently. 13. Volume 11A Certification Question Question: Write one browser-side JavaScript function using async/await that keeps these outcomes distinct: (1) network/transport failure before a Response exists, (2) HTTP 4xx/5xx after a Response exists, and (3) invalid JSON in an otherwise received Response. Then explain why error instanceof TypeError alone cannot reliably identify invalid JSON, and state what the PHP server must still validate even if the browser validates the form. Pass standard: Charlie must identify the three stages correctly, keep their failure evidence separate, stay in browser JavaScript for the client-side portion, avoid environment-specific assumptions not established by evidence, and preserve the server-side trust boundary. After this focused retest passes, repeat the original Volume 11 certification question.