Summary
Add comprehensive request and response validation with schema validation, data sanitization, and contract testing capabilities.
Motivation
Validation is crucial for:
- Data Integrity: Ensure requests/responses meet expected schemas
- Security: Validate and sanitize input data to prevent attacks
- API Contracts: Enforce OpenAPI/JSON Schema specifications
- Development Quality: Catch integration issues early
- Documentation: Living documentation through validation schemas
- Error Prevention: Fail fast on invalid data
- Type Safety: Runtime type checking for dynamic data
Proposed API
// Schema-based validation
$response = fetch('/api/users/123')
->validateResponse(UserSchema::class)
->validateStatus([200, 404])
->expectJson()
->get();
// Request validation
$response = fetch('/api/users', [
'method' => 'POST',
'json' => $userData,
'validate_request' => CreateUserSchema::class,
'validate_response' => UserResponseSchema::class,
]);
// OpenAPI contract validation
$client = fetch_client()
->withOpenApiSpec('/path/to/api-spec.yaml')
->validateContracts(true);
// Custom validation rules
$response = fetch('/api/data')
->validateResponse([
'id' => 'required|integer|min:1',
'email' => 'required|email',
'status' => 'required|in:active,inactive',
'metadata' => 'array',
])
->onValidationFailure(function (ValidationException $e) {
$this->logger->error('Response validation failed', $e->getErrors());
});
Implementation Details
interface ValidatorInterface
{
public function validate(mixed $data, array|string|object $schema): ValidationResult;
public function sanitize(mixed $data, array $rules): mixed;
}
class ValidationResult
{
public function __construct(
private bool $isValid,
private array $errors = [],
private mixed $validatedData = null
) {}
public function isValid(): bool { return $this->isValid; }
public function getErrors(): array { return $this->errors; }
public function getValidatedData(): mixed { return $this->validatedData; }
}
// JSON Schema validator
class JsonSchemaValidator implements ValidatorInterface
{
public function validate(mixed $data, array|string|object $schema): ValidationResult
{
$validator = new \JsonSchema\Validator();
$validator->validate($data, $schema);
return new ValidationResult(
$validator->isValid(),
$validator->getErrors(),
$data
);
}
}
// Laravel-style validator
class RuleBasedValidator implements ValidatorInterface
{
public function validate(mixed $data, array|string|object $rules): ValidationResult
{
$errors = [];
$validatedData = [];
foreach ($rules as $field => $rule) {
$value = $data[$field] ?? null;
$fieldErrors = $this->validateField($field, $value, $rule);
if (!empty($fieldErrors)) {
$errors[$field] = $fieldErrors;
} else {
$validatedData[$field] = $this->sanitizeValue($value, $rule);
}
}
return new ValidationResult(
empty($errors),
$errors,
$validatedData
);
}
}
Use Cases
API Contract Testing
$client = fetch_client()
->withOpenApiSpec('/api/openapi.yaml')
->validateContracts(true)
->onContractViolation(function (ContractViolation $violation) {
$this->testReporter->recordViolation($violation);
});
Data Sanitization
$response = fetch('/api/user-input')
->sanitizeResponse([
'name' => 'string|trim|escape',
'email' => 'email|lowercase',
'age' => 'integer|min:0|max:150',
]);
Type-Safe API Responses
class UserResponse
{
public function __construct(
public int $id,
public string $name,
public string $email,
public array $permissions
) {}
}
$user = fetch('/api/users/123')
->validateResponse(UserResponse::class)
->getTypedData(); // Returns UserResponse instance
Benefits
- Reliability: Catch data issues before they cause problems
- Security: Validate and sanitize all external data
- Documentation: Schemas serve as living documentation
- Testing: Automated contract testing
- Developer Experience: Clear error messages and type safety
Priority
Medium Impact, Medium Effort - Important for production APIs but not critical for basic functionality.
Summary
Add comprehensive request and response validation with schema validation, data sanitization, and contract testing capabilities.
Motivation
Validation is crucial for:
Proposed API
Implementation Details
Use Cases
API Contract Testing
Data Sanitization
Type-Safe API Responses
Benefits
Priority
Medium Impact, Medium Effort - Important for production APIs but not critical for basic functionality.