Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Force Host Laravel Package

14four/laravel-force-host

Middleware for Laravel that forces a single canonical host for all requests. Automatically redirects to your configured domain (and optionally scheme), preventing duplicate URLs across www/non-www and improving SEO, cache consistency, and security.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require 14four/laravel-force-host
    

    Publish the config file (if needed):

    php artisan vendor:publish --provider="14four\ForceHost\ForceHostServiceProvider"
    
  2. Basic Configuration Edit config/force-host.php to define allowed hosts:

    'hosts' => [
        'app.example.com',
        '*.example.com', // Supports wildcards
    ],
    
  3. First Use Case Enable the middleware in app/Http/Kernel.php:

    protected $middleware = [
        // ...
        \14four\ForceHost\ForceHostMiddleware::class,
    ];
    

    Now, any request with a Host header not matching the allowed list will be rejected with a 403 Forbidden.


Implementation Patterns

Middleware Integration

  • Global Protection: Add to $middleware in Kernel.php to enforce host validation across all routes.
  • Route-Specific Protection: Apply only to sensitive routes:
    Route::get('/admin', function () {
        // ...
    })->middleware(\14four\ForceHost\ForceHostMiddleware::class);
    

Dynamic Host Validation

  • Custom Logic: Extend the middleware by binding a custom validator:
    use 14four\ForceHost\ForceHostMiddleware;
    
    $middleware = new ForceHostMiddleware(app('validator'), function ($host) {
        return str_contains($host, 'internal.');
    });
    

Wildcard Support

  • Use *.example.com to allow subdomains. Wildcards are resolved via regex:
    'hosts' => [
        '*.staging.example.com',
    ],
    

Integration with Trusted Proxies

  • If behind a proxy (e.g., Nginx, Cloudflare), ensure trusted_proxies in app/config/trustedproxies.php includes the proxy IPs. The package respects Laravel’s proxy detection.

Gotchas and Tips

Pitfalls

  • Case Sensitivity: Hostnames are case-insensitive by default, but wildcards (*.example.com) are case-sensitive in regex. Test edge cases like Example.COM.
  • Proxy Headers: If using proxies, ensure X-Forwarded-Host is trusted. Misconfiguration may bypass validation.
  • Local Development: Disable middleware in Kernel.php for local testing:
    if (app()->environment('local')) {
        $middleware = [];
    }
    

Debugging

  • Logs: Enable debug mode in config/force-host.php:
    'debug' => env('FORCE_HOST_DEBUG', false),
    
    Logs rejected hosts to storage/logs/laravel.log.
  • Custom Responses: Override the default 403 response by binding a closure to the middleware:
    $middleware = new ForceHostMiddleware(app('validator'), null, function () {
        return response()->json(['error' => 'Invalid host'], 403);
    });
    

Extension Points

  • Custom Validators: Replace the default validator by binding a new instance:
    $validator = app('validator');
    $validator->extend('host_allowed', function ($attribute, $value, $parameters) {
        return in_array($value, ['app.example.com', 'api.example.com']);
    });
    
  • Event Listeners: Listen for forcehost.rejected events to log or alert on blocked requests:
    Event::listen('forcehost.rejected', function ($request, $host) {
        Log::warning("Blocked host: {$host} from IP: {$request->ip()}");
    });
    

Performance

  • Caching: Wildcard host checks are regex-based. For high-traffic apps, pre-compile regex patterns in a service provider’s boot method:
    public function boot()
    {
        $this->app->singleton('forcehost.patterns', function () {
            return collect(config('force-host.hosts'))
                ->map(fn ($host) => preg_quote($host, '/'))
                ->map(fn ($host) => str_replace('\*', '.*', $host))
                ->map(fn ($host) => "/^{$host}$/i")
                ->values();
        });
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel