Validating Inputs in a REST API
What is Input Validation?
Section titled “What is Input Validation?”- Input validation is the process of verifying that client-provided data meets expected formats, types, and constraints before processing it.
- Without validation, REST APIs are vulnerable to security threats (e.g., SQL injection, command injection), broken functionality, and unexpected behavior from malformed data.
- Example:
- Valid:
{"user_id": 123, "name": "Quacker"} - Invalid:
{"user_id": "abc", "name": "##123@@"}
- Valid:
- Example:
- Proper validation ensures data integrity, reliability, and a better user experience by providing clear error messages when inputs are invalid.
What to Validate?
Section titled “What to Validate?”Input Sources
Section titled “Input Sources”For a REST API, inputs can be provided by the client request in the following ways:
- Query string parameters (e.g.,
GET /species?limit=10) - URL path parameters (e.g.,
GET /players/123) - Request body (e.g., JSON in a POST, PUT, or PATCH request)
- Request headers (e.g.,
Accept,Authorization)
Typical Validation Rules
Section titled “Typical Validation Rules”When processing user or client-provided data in a REST API, you’ll need to validate:
- Presence: Is a required field provided?
- Type: Is the input an integer, string, boolean, etc.?
- Format: Does it match a pattern (e.g., UUID for resource IDs, ISO 8601 for timestamps, valid enum values for status fields)?
- Range/Length: Is it within acceptable bounds (e.g., pagination limit 1-100, offset >= 0, price > 0)?
- Business rules: Does it make sense in your domain (e.g., stock quantity available, valid status transitions)?
How to Validate Inputs in PHP?
Section titled “How to Validate Inputs in PHP?”There are two main approaches to validating inputs in PHP:
- Native PHP functions:
filter_var()for sanitizing and validating common types (e.g., email, URL).isset(),empty()for checking presence.- Type casting/checking with
is_int(),is_string(), etc. - Example:
$email = 'test@example.com';if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {echo 'Invalid email format';}
- Third-party libraries: For more complex validation, libraries like Valicomb ↗ provide built-in rules (e.g.,
required,email,min,max) and reduce boilerplate compared to writing manual checks. Valicomb is a simple, stand-alone validation library with no dependencies.
Resources:
Example Implementation
Section titled “Example Implementation”- Scenario:
POST /playersto create a player. - Validation Rules:
name: String, 2-50 chars, required.age: Integer, 18-110, optional.
- When validation fails, return a
422 Unprocessable Entitystatus with a structured JSON error response. Be specific in error messages, but avoid leaking internal details. - See also: Responding to Invalid Input.
public function handleCreatePlayer(Request $request, Response $response): Response{ $data = $request->getParsedBody();
$errors = [];
// Validate name if (!isset($data['name']) || empty($data['name'])) { $errors[] = ['field' => 'name', 'message' => 'name is required']; } elseif (strlen($data['name']) < 2 || strlen($data['name']) > 50) { $errors[] = ['field' => 'name', 'message' => 'name must be between 2 and 50 characters']; }
// Validate age (optional) if (isset($data['age']) && (!is_numeric($data['age']) || $data['age'] < 18 || $data['age'] > 110)) { $errors[] = ['field' => 'age', 'message' => 'age must be an integer between 18 and 110']; }
if (!empty($errors)) { return $this->renderJson($response, [ 'status' => 'error', 'message' => 'Validation failed', 'details' => $errors ], 422); }
// Validation passed: proceed with creating the player...}Input Validation Checklist
Section titled “Input Validation Checklist”- Validate early: Check inputs at the controller or service layer.
- Use schemas: Define strict data models (e.g., JSON Schema, OpenAPI).
- Sanitize inputs: Even after validation, use
filter_var()or similar to escape unsafe characters before database insertion. - Use HTTP Status Codes:
- 400: Bad Request (malformed JSON).
- 422: Unprocessable Entity (validation errors).
- Centralize validation: Move rules and messages to a separate class or helper class for reusability.
- Log errors: Log validation failures for debugging or security monitoring.
- Document your API: Use OpenAPI/Swagger to specify expected inputs and error responses.
- Handle edge cases: Test with empty strings, null values, malformed JSON, and oversized payloads.