Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c24d290f4 | ||
|
|
396207d6b0 | ||
|
|
7a35de80d0 | ||
|
|
9f0d41d827 | ||
|
|
562448f576 | ||
|
|
cb911a3c04 | ||
|
|
06ee9a5016 | ||
|
|
0113b0112b | ||
|
|
ae8d4bd432 | ||
|
|
c9fbf64472 |
57
README.md
57
README.md
@@ -230,7 +230,9 @@ laravel-api-kit/
|
||||
│ ├── sanctum.php # Token auth config
|
||||
│ └── scramble.php # API docs config
|
||||
├── routes/
|
||||
│ └── api.php # API routes with versioning
|
||||
│ ├── api.php # API routes entry point
|
||||
│ └── api/
|
||||
│ └── v1.php # Version 1 routes
|
||||
├── tests/
|
||||
│ └── Feature/Api/V1/
|
||||
│ └── AuthTest.php # Authentication tests
|
||||
@@ -241,7 +243,7 @@ laravel-api-kit/
|
||||
|
||||
## API Versioning
|
||||
|
||||
This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-apiroute) for API versioning with support for:
|
||||
This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-apiroute) v2.x for API versioning with support for:
|
||||
|
||||
- **URI Path** (default): `/api/v1/users`, `/api/v2/users`
|
||||
- **Header**: `X-API-Version: 2`
|
||||
@@ -252,22 +254,34 @@ This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-ap
|
||||
|
||||
1. Create controllers in `app/Http/Controllers/Api/V2/`
|
||||
2. Create requests in `app/Http/Requests/Api/V2/`
|
||||
3. Update `routes/api.php`:
|
||||
3. Create route file `routes/api/v2.php`:
|
||||
|
||||
```php
|
||||
use Grazulex\ApiRoute\Facades\ApiRoute;
|
||||
<?php
|
||||
|
||||
// Version 2 - New current version
|
||||
ApiRoute::version('v2', function () {
|
||||
Route::post('register', [V2\AuthController::class, 'register']);
|
||||
// ... more routes
|
||||
})->current();
|
||||
use App\Http\Controllers\Api\V2\AuthController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// Version 1 - Mark as deprecated
|
||||
ApiRoute::version('v1', function () {
|
||||
Route::post('register', [V1\AuthController::class, 'register']);
|
||||
// ... existing routes
|
||||
})->deprecated('2025-06-01')->sunset('2025-12-01');
|
||||
Route::post('register', [AuthController::class, 'register']);
|
||||
// ... more routes
|
||||
```
|
||||
|
||||
4. Update `config/apiroute.php`:
|
||||
|
||||
```php
|
||||
'versions' => [
|
||||
'v1' => [
|
||||
'routes' => base_path('routes/api/v1.php'),
|
||||
'status' => 'deprecated',
|
||||
'deprecated_at' => '2025-06-01',
|
||||
'sunset_at' => '2025-12-01',
|
||||
'successor' => 'v2',
|
||||
],
|
||||
'v2' => [
|
||||
'routes' => base_path('routes/api/v2.php'),
|
||||
'status' => 'active',
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
### Deprecation Headers
|
||||
@@ -275,8 +289,8 @@ ApiRoute::version('v1', function () {
|
||||
When accessing deprecated versions, responses include RFC-compliant headers:
|
||||
|
||||
```http
|
||||
Deprecation: @1717200000
|
||||
Sunset: Sun, 01 Dec 2025 00:00:00 GMT
|
||||
Deprecation: Sun, 01 Jun 2025 00:00:00 GMT
|
||||
Sunset: Mon, 01 Dec 2025 00:00:00 GMT
|
||||
Link: </api/v2>; rel="successor-version"
|
||||
```
|
||||
|
||||
@@ -574,14 +588,11 @@ class PostResource extends JsonResource
|
||||
|
||||
4. **Add Routes:**
|
||||
```php
|
||||
// routes/api.php
|
||||
ApiRoute::version('v1', function () {
|
||||
// routes/api/v1.php
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
// ... existing routes
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::apiResource('posts', PostController::class);
|
||||
});
|
||||
})->current();
|
||||
Route::apiResource('posts', PostController::class);
|
||||
});
|
||||
```
|
||||
|
||||
5. **Create Tests:**
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
"keywords": ["laravel", "api", "rest", "starter-kit", "sanctum"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"php": "^8.3",
|
||||
"dedoc/scramble": "^0.12",
|
||||
"grazulex/laravel-apiroute": "^1.0",
|
||||
"grazulex/laravel-apiroute": "^2.0",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/sanctum": "^4.0",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
@@ -21,8 +21,8 @@
|
||||
"laravel/pint": "^1.24",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"pestphp/pest": "^3.0",
|
||||
"pestphp/pest-plugin-laravel": "^3.0"
|
||||
"pestphp/pest": "^4.0",
|
||||
"pestphp/pest-plugin-laravel": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
989
composer.lock
generated
989
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,28 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Versions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define your API versions here. Each version has its own route file,
|
||||
| middleware, and lifecycle status.
|
||||
|
|
||||
*/
|
||||
'versions' => [
|
||||
'v1' => [
|
||||
'routes' => base_path('routes/api/v1.php'),
|
||||
'middleware' => [],
|
||||
'status' => 'active',
|
||||
'deprecated_at' => null,
|
||||
'sunset_at' => null,
|
||||
'successor' => null,
|
||||
'documentation' => null,
|
||||
'rate_limit' => null,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Detection Strategy
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Api\V1\AuthController;
|
||||
use Grazulex\ApiRoute\Facades\ApiRoute;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| API routes are versioned using grazulex/laravel-apiroute.
|
||||
| API routes are versioned using grazulex/laravel-apiroute v2.x.
|
||||
| Versions are defined in config/apiroute.php and route files are
|
||||
| located in routes/api/{version}.php
|
||||
|
|
||||
| Supports URI path, header, query, and Accept header detection.
|
||||
| See config/apiroute.php for configuration options.
|
||||
|
|
||||
@@ -17,13 +16,17 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
// Version 1 - Current stable version
|
||||
ApiRoute::version('v1', function () {
|
||||
// Public routes
|
||||
Route::post('register', [AuthController::class, 'register'])->name('api.v1.register');
|
||||
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login');
|
||||
// Public routes with auth rate limiter (5/min - brute force protection)
|
||||
Route::middleware('throttle:auth')->group(function () {
|
||||
Route::post('register', [AuthController::class, 'register'])->name('api.v1.register');
|
||||
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login');
|
||||
});
|
||||
|
||||
// Protected routes
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
// Protected routes with authenticated rate limiter (120/min)
|
||||
Route::middleware(['auth:sanctum', 'throttle:authenticated'])->group(function () {
|
||||
Route::post('logout', [AuthController::class, 'logout'])->name('api.v1.logout');
|
||||
Route::get('me', [AuthController::class, 'me'])->name('api.v1.me');
|
||||
});
|
||||
})->current();
|
||||
})
|
||||
->current()
|
||||
->rateLimit(60); // Global rate limit: 60 requests/minute for v1
|
||||
|
||||
23
routes/api/v1.php
Normal file
23
routes/api/v1.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Api\V1\AuthController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API V1 Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Routes for API version 1.
|
||||
|
|
||||
*/
|
||||
|
||||
// Public routes
|
||||
Route::post('register', [AuthController::class, 'register'])->name('api.v1.register');
|
||||
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login');
|
||||
|
||||
// Protected routes
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::post('logout', [AuthController::class, 'logout'])->name('api.v1.logout');
|
||||
Route::get('me', [AuthController::class, 'me'])->name('api.v1.me');
|
||||
});
|
||||
@@ -1,6 +1,4 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// Web routes disabled - API only application
|
||||
// Scramble documentation available at /docs/api
|
||||
|
||||
Reference in New Issue
Block a user