sabservis / api
Installs: 1 003
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/sabservis/api
Requires
- php: >= 8.1
- ext-fileinfo: *
- ext-mbstring: *
- igorpocta/data-mapper: ^1.3
- nette/di: ^3.2
- psr/simple-cache: ^3.0
- symfony/cache: ^6.4
- tracy/tracy: ^2.10
Requires (Dev)
- phpstan/phpstan: ^1.12
- phpunit/phpunit: ^10.5
- slevomat/coding-standard: ^8.27
README
Moderní PHP REST API framework pro Nette s automatickou OpenAPI dokumentací.
Features
- Deklarativní routing - Definuj endpointy pomocí PHP 8 atributů
- OpenAPI 3.0 - Automatické generování dokumentace
- Type-safe - Plná podpora typovaných parametrů, enumů, DTO
- Middleware - Rozšiřitelný middleware pipeline (CORS, rate limiting, auth)
- Validace - Vestavěná validace requestů s detailními chybami
- File Uploads - Server-side MIME validace, filename sanitizace, symlink ochrana
- Security - Rate limiting, request size limits, path traversal ochrana
Quick Start
composer require sabservis/api
# config.neon extensions: api: Sabservis\Api\DI\ApiExtension api: debug: %debugMode% maxRequestBodySize: 10485760 # 10MB limit (DoS ochrana) trustedProxies: # Za reverse proxy (nginx, Cloudflare) - 10.0.0.0/8 - 172.16.0.0/12 router: basePath: /api
// www/index.php Bootstrap::boot() ->createContainer() ->getByType(ApiApplication::class) ->run();
#[Tag(name: 'users')] class UserController implements Controller { #[Get(path: '/users/{id}')] public function get(int $id): UserDto { return $this->users->find($id); } #[Post(path: '/users')] #[RequestBody(ref: CreateUserDto::class)] public function create(ApiRequest $request): ApiResponse { $dto = $request->getEntity(); return ApiResponse::created($this->users->create($dto)); } }
File Uploads
Bezpečné nahrávání souborů s automatickou MIME validací:
#[Post(path: '/documents')] #[FileUpload(name: 'file', allowedTypes: ['application/pdf', 'image/jpeg', 'image/png'])] public function upload(ApiRequest $request): ApiResponse { $file = $request->getUploadedFile('file'); // MIME type je automaticky validován pomocí finfo (magic bytes) // Klientský Content-Type header je ignorován (nelze spoofovat) // Bezpečný přesun - vytvoří adresář, sanitizuje název, nepřepíše existující $path = $file->moveToDirectory('/uploads'); return ApiResponse::created(['filename' => basename($path)]); }
Bezpečnostní funkce:
- Server-side MIME detekce (
finfo) - klient nemůže spoofovat typ souboru - Automatická filename sanitizace - ochrana proti path traversal (
../) - Symlink ochrana - volitelné blokování symlinků
- Validace
allowedTypesna úrovni dispatcheru (415 Unsupported Media Type)
// Manuální validace v kontroleru $file->getValidatedContentType(); // Server-side MIME type $file->isAllowedType(['application/pdf']); // true/false $file->assertAllowedType(['application/pdf']); // throws exception $file->getSanitizedName(); // Bezpečný filename // Bezpečný přesun souboru $file->moveTo($path); // Nepřepíše existující (safe default) $file->moveTo($path, overwrite: true); // Explicitní přepsání $file->moveToDirectory($dir); // Auto: vytvoří dir, sanitizuje název $file->moveToDirectory($dir, 'custom.pdf'); // Vlastní název (sanitizovaný)
Validace request DTO
Framework automaticky validuje request DTO po deserializaci pomocí DataMapperEntityValidator. Na DTO properties používej validační atributy z knihovny pocta/data-mapper:
use Pocta\DataMapper\Validation\NotBlank; use Pocta\DataMapper\Validation\Email; use Pocta\DataMapper\Validation\Valid; class CreateUserDto { #[NotBlank] public string $name; #[Email] public string $email; #[Valid] public AddressDto $address; // rekurzivní validace }
Při odeslání nevalidních dat vrátí framework 422 s detailními chybami:
{
"code": 422,
"message": "Request body contains an error. See context for details.",
"context": {
"validation": {
"name": ["This field is required."],
"email": ["This value is not a valid email address."],
"address.street": ["This field is required."]
}
}
}
Vypnutí validace
api: validator: null
Vlastní validátor
Implementuj EntityValidator interface a zaregistruj v konfiguraci:
class SymfonyEntityValidator implements EntityValidator { public function validate(object $entity, array|string|null $validationGroups = null): void { // vlastní validační logika // při chybě throw new ValidationException()->withFields([...]) } }
api: validator: App\Api\Validator\SymfonyEntityValidator
Documentation
| Téma | Popis |
|---|---|
| Getting Started | Instalace, konfigurace, první endpoint |
| Controllers & Routing | Definice endpointů, HTTP metody, path parametry |
| Request & Response | Práce s ApiRequest a ApiResponse |
| Parameters & Validation | Query, path, header parametry, validace |
| OpenAPI | Automatická dokumentace, Schema atributy |
| Middleware | Vestavěné middleware, vlastní middleware |
| Security | Rate limiting, file security, best practices |
| Testing | ApiTestClient, testování controllerů |
Requirements
- PHP 8.1+
- Nette DI 3.2+
- Symfony Cache 6.4+