Server-side safety
Build a complete feedback form
Combine accessible HTML, browser validation, FormData, HTTP handling, server validation, security controls, and useful result states.
8 minute lesson
Build a feedback form that works from the browser all the way to a server decision.
The form collects:
- name
- email address
- category
- message
- optional screenshot
Start with native HTML
Give every control a visible label and stable name. Group related choices with fieldset and legend. Add concise help before the fields that need it.
Use /feedback as the action and POST as the method. Add multipart encoding for the screenshot. The form must work when JavaScript is unavailable.
Define the server contract
Write down the accepted fields before implementing the endpoint.
Validate required values, lengths, the category allowlist, and screenshot limits. Treat the original filename and media type as untrusted. Generate a storage name and keep the upload outside executable application files.
Return field errors without erasing valid values. After a successful native POST, redirect to a GET confirmation page.
Add CSRF protection if the form uses cookie authentication. Add request-size and rate limits. Do not log the message body, token, or uploaded bytes by default.
Add JavaScript as an enhancement
Intercept the form’s submit event and send FormData with fetch(). Show idle, pending, success, validation-error, and network-error states.
Disable the active submitter while the request is pending, but make the endpoint safe if the request arrives twice. Reset only after confirmed success.
If the script fails, the native submission path must still work.
Test the failures
Complete the form with only a keyboard. Then test:
- empty and overlong values
- a category not present in the page
- a large file and a renamed non-image
- a missing or invalid CSRF token when required
- repeated submission
- offline mode and a server error
- refresh after success
- 200% zoom and narrow screens
You are done when each failure produces an understandable result, preserves safe work, and leaves the form usable.
Lesson completed