3.7 KiB
3.7 KiB
API Gateway in this Laravel App
This app acts as a thin API Gateway in front of an external backend API. All feature controllers proxy to the external API and no longer access a local database.
Configuration
Set these env vars (see config/services.php):
BACKEND_API_BASE(default:http://casinoapi.test)BACKEND_API_TOKEN(required, Bearer service token)BACKEND_API_TIMEOUT(float seconds, default8.0)
Standard Upstream Headers
Every upstream call includes:
Authorization: Bearer {BACKEND_API_TOKEN}X-User-Id: <laravel_auth_user_id>X-User-Device: <sha256(User-Agent|SessionId)>X-User-IP: <sha256(ip)>Accept: application/json(SSE endpoints usetext/event-stream)
Timeouts & Retries
- Timeout:
8seconds (configurable viaBACKEND_API_TIMEOUT). - Retries: GET requests retry 2x on timeout/5xx with 100ms backoff. Mutations (POST/PATCH/DELETE) do not retry.
Error Mapping (Gateway → Frontend)
- Upstream 4xx → same 4xx, body:
{ "error": "client_error", "message": "Invalid request" } - Upstream 5xx (reachable server) →
503, body:{ "error": "service_unavailable", "message": "Internal server error" } - Network/Timeout/Unreachable →
502, body:{ "error": "bad_gateway", "message": "API server not reachable" }
Shared Building Blocks
App\Services\BackendHttpClientcentralizes Base URL, token, timeout, GET retry policy, and user-context headers.App\Http\Controllers\Concerns\ProxiesBackendprovides the error mapping helpers used by all controllers.
Domains proxied
- Chat:
GET/POST /api/chat,POST /api/chat/{id}/react→ upstream/chat - Support:
/api/support/*→ upstream/support/*(SSE passthrough for/stream) - Vault:
/api/wallet/vault*→ upstream/wallet/vault* - Social/Profile/Friends: profile page & actions → upstream
/users/*,/social/*,/friends/* - Bonuses/Promos:
/api/bonuses/app,/api/user/bonuses,/api/promos/apply→ upstream/bonuses/app,/users/me/bonuses,/promos/apply - Guilds: pages & actions → upstream
/guilds* - Wallet/VIP: pages/actions → upstream
/wallet,/vip-levels* - Admin: pages/actions → upstream
/admin/*
Frontend Contract Notes
- Internal routes (
/api/...or page routes) remain stable. Controllers may reshape upstream JSON minimally to the shapes already expected by Vue components. - Example: Chat GET maps upstream
{ messages: [...] }to{ data: [...], last_id }and flattens user + reactions.
Example: Faking Upstream in Tests
All proxy feature tests use Http::fake() to simulate the external API.
use Illuminate\Support\Facades\Http;
Http::fake([
config('services.backend.base') . '/chat*' => Http::response([
'messages' => [ ['id'=>1,'user_id'=>2,'username'=>'dolo','avatar'=>null,'message'=>'hi','reactions'=>[],'created_at'=>now()->toIso8601String()] ],
], 200),
]);
$res = $this->actingAs($user)->get('/api/chat?limit=50');
$res->assertStatus(200)->assertJsonStructure(['data','last_id']);
Running Tests
- Ensure
.env.testingsetsBACKEND_API_BASE(any value is fine) and no real external calls are required (we fake all withHttp::fake()). - Run:
php artisan testorvendor\bin\phpunit.
SSE Support (Support Chat)
GET /api/support/streampasses throughtext/event-streamfrom upstream. If upstream is not OK or stream fails to start, the Gateway returns503 service_unavailableJSON.
Extending
- Add new upstream endpoints by injecting
BackendHttpClientinto your controller and usingget/post/patch/delete/postMultipart. - Always use
ProxiesBackendhelpers to map errors consistently.