Frontend to API Explained: Requests, Validation and Error Handling
Follow a browser request through an API and database, with a JavaScript example that handles HTTP errors and explains where security checks belong.
What happens when a page loads data?
A browser sends a request to a server route. The server checks the request and access permissions, reads the required records, and returns a response. The frontend checks the result and renders either data or a useful error state.
This separation matters: the browser controls presentation, while the server must enforce access. Hiding an admin button cannot protect an admin endpoint.
A browser fetch example
The route below is illustrative: your server must implement GET /api/courses before the live request can work. The function accepts a fetch implementation so its behaviour can also be exercised with a local mock.
async function loadCourses(fetcher = fetch) {
const response = await fetcher('/api/courses', {
headers: { Accept: 'application/json' }
});
if (!response.ok) {
throw new Error('Course request failed: ' + response.status);
}
const data = await response.json();
if (!Array.isArray(data)) {
throw new Error('Expected a course list');
}
return data;
}
const mockFetch = async () => ({
ok: true, status: 200,
json: async () => [{ id: 1, title: 'SQL Basics' }]
});
loadCourses(mockFetch)
.then(courses => console.log(courses[0].title))
.catch(error => console.error(error.message));
Expected mock output: SQL Basics. To use the real endpoint, call loadCourses() instead. A successful mock proves this small code path, not that your server, network or database works.
Why is response.ok necessary?
A fetch promise does not reject merely because the server returned an HTTP error such as 404. Inspect the status before treating the body as successful data. Network failures can reject the promise, and malformed JSON can fail while reading it. Handle these paths and avoid displaying private server diagnostics to visitors.
Which checks belong on the server?
- Validate query parameters and request bodies with explicit allowed fields.
- Authenticate protected routes and authorize the action on each record.
- Use parameterized database queries and return only required public fields.
- Keep credentials and service keys on the server, outside frontend bundles.
- Apply limits and logging appropriate to the endpoint.
Client validation improves usability, but callers can bypass it. Rendering a course title through text content is safer than injecting untrusted HTML. Authentication, authorization and safe rendering solve different problems; one does not replace the others.
What should the user see?
Show loading while the request is pending, a helpful empty state for a valid empty list, and a recoverable error state for failure. Prevent repeated submissions while a write is in progress. If a failed request is retried, avoid duplicate writes through a server-side strategy suited to the operation.
Practice: change the mock to ok false with status 404. The expected error is Course request failed: 404. Then make json return an object; the expected error is Expected a course list. Finally describe how you would test that a student cannot call an admin update route.
Learning and reference
Full Stack Development course.
MDN: Using Fetch.
AI Leaf Global Learn provides classroom learning in Mudichur/Tambaram, Chennai, and online learning across India. Confirm current batches and curriculum. Prepared by AI Leaf Global Learn; the real endpoint is illustrative and is not claimed to exist on this website.