Laravel Cloud is here! Zero-config managed infrastructure for Laravel apps. Deploy now.

Passage: A Lightweight API Proxy Gateway for Laravel

Last updated on by

Passage: A Lightweight API Proxy Gateway for Laravel image

Passage is a Laravel package by Morcen Chavez that lets your app sit between a client and an external API, forwarding requests and responses while keeping full control over authentication, headers, and payload transformation — all through familiar Laravel routing and middleware.

The typical use case is when you need to call a third-party API from your frontend but don't want to expose API keys, need to normalize payloads, or want to enforce validation and auth logic in one place. Instead of building a custom proxy from scratch, Passage gives you a structured way to do it with minimal boilerplate.

Defining Routes

Routes are registered using the Passage facade, right alongside your regular routes. The {path?} wildcard captures any sub-path and forwards it upstream:

use Morcen\Passage\Facades\Passage;
 
Passage::get('github/{path?}', GithubPassageController::class);
Passage::post('stripe/{path?}', StripePassageController::class);
Passage::any('payments/{path?}', PaymentsPassageController::class);

These support the standard HTTP methods — get, post, put, patch, delete, and any.

Creating a Handler

Each route points to a handler class that controls how requests are forwarded and responses are returned. Generate one with:

php artisan passage:controller GithubPassageController

Handlers extend PassageHandler and can implement three methods:

  • getOptions() — sets the upstream base URI and Guzzle options (timeouts, headers, etc.)
  • getRequest() — transforms or injects credentials into the outgoing request
  • getResponse() — transforms the upstream response before it reaches the client

A minimal handler might look like this:

class GithubPassageController extends PassageHandler
{
public function getOptions(): array
{
return [
'base_uri' => 'https://api.github.com/',
];
}
 
public function getRequest(Request $request): Request
{
return $this->withBearerToken($request, config('services.github.token'));
}
}

Note the trailing slash on base_uri — it's required for path forwarding to work correctly.

Built-in Authentication Helpers

Passage ships with three authentication traits you can use inside getRequest():

  • Bearer token$this->withBearerToken($request, $token)
  • API key (as a header or query param) — $this->withApiKey($request, $key) or $this->withApiKeyQuery($request, $key, 'api_key')
  • HMAC signing$this->withHmacSignature($request, $secret)

You can also scaffold a handler with auth pre-wired:

php artisan passage:controller StripePassageController --with-auth=apikey
php artisan passage:controller PaymentsPassageController --with-auth=hmac

Security

Passage automatically strips sensitive client headers — cookies, authorization, proxy-authorization — before forwarding requests upstream. If you need to selectively pass certain headers through (like forwarding the client's Authorization header), have your handler implement the AcceptsClientHeaders interface and define the allowedClientHeaders() method to return an allowlist:

class GithubPassageController extends PassageHandler implements AcceptsClientHeaders
{
public function allowedClientHeaders(): array
{
return ['authorization'];
}
}

You can also restrict which hosts can be proxied by setting PASSAGE_ENFORCE_ALLOWED_HOSTS=true in your environment.

Inbound Validation and Resilience

Handlers can validate incoming requests before they ever reach the upstream service by implementing ValidatesInboundRequest. Define Laravel validation rules in a rules() method, and any failures return a 422 — no upstream call is made.

use Morcen\Passage\Contracts\ValidatesInboundRequest;
 
class StripePassageController extends PassageHandler implements ValidatesInboundRequest
{
public function getOptions(): array
{
return ['base_uri' => 'https://api.stripe.com/'];
}
 
public function rules(): array
{
return [
'amount' => ['required', 'integer', 'min:1'],
'currency' => ['required', 'string', 'size:3'],
];
}
}

For resilience, withRetry() adds automatic retry with exponential backoff:

class PaymentsPassageController extends PassageHandler
{
public function getOptions(): array
{
return array_merge(
['base_uri' => 'https://payments.example.com/'],
$this->withRetry(3, 200), // 3 retries, 200ms initial delay
);
}
}

Passage also supports response caching for GET/HEAD routes and streaming responses for large payloads.

Useful Artisan Commands

  • php artisan passage:list — lists all registered proxy routes
  • php artisan passage:health — checks connectivity to upstream services

You can also disable all proxying without touching your routes by setting PASSAGE_ENABLED=false in your .env.


Passage is a clean solution for scenarios where you need a lightweight API proxy inside an existing Laravel app without reaching for a full enterprise gateway. Learn more and explore the source code on GitHub.

Yannick Lyn Fatt photo

Staff Writer at Laravel News and Full stack web developer.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
PhpStorm logo

PhpStorm

The go-to PHP IDE with extensive out-of-the-box support for Laravel and its ecosystem.

PhpStorm
Laravel Cloud logo

Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Cloud
Acquaint Softtech logo

Acquaint Softtech

Acquaint Softtech offers AI-ready Laravel developers who onboard in 48 hours at $3000/Month with no lengthy sales process and a 100 percent money-back guarantee.

Acquaint Softtech
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
Passage: A Lightweight API Proxy Gateway for Laravel image

Passage: A Lightweight API Proxy Gateway for Laravel

Read article
PestPHP Intellisense in Laravel VS Code Extension v1.7.0 image

PestPHP Intellisense in Laravel VS Code Extension v1.7.0

Read article
Drop in comments for Filament with Commentions image

Drop in comments for Filament with Commentions

Read article
Laravel Starter Kits Now Include Toast Notifications image

Laravel Starter Kits Now Include Toast Notifications

Read article
Ship AI with Laravel: Stop Your AI Agent from Guessing image

Ship AI with Laravel: Stop Your AI Agent from Guessing

Read article
Laravel Cloud Adds Path Blocking to Prevent Bots From Waking Hibernated Apps image

Laravel Cloud Adds Path Blocking to Prevent Bots From Waking Hibernated Apps

Read article