laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.54k stars 11.02k forks source link

When using closure routing, using middleware will report an error #45192

Closed peibinzhu closed 1 year ago

peibinzhu commented 1 year ago

Description:

Using $request->route()->getController() in middleware will cause an error when using closure routing,please fix this.

Error message:

str_contains(): Argument #1 ($haystack) must be of type string, Closure given {"exception":"[object] (TypeError(code: 0): str_contains(): Argument #1 ($haystack) must be of type string, Closure given at /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Support/Str.php:242)

I'm currently only able to judge each middleware, which is not very friendly.

class RequestPayload
{
    public function handle(Request $request, Closure $next): mixed
    {
        if ($request->route()->getActionName() == 'Closure') {
            return $next($request);
        }

        //...

        return $next($request);
    }
}

Steps To Reproduce:

Add a closure route in routes/web.php

Route::get('/', function () {
    return response()->json(['msg'=>'Hello World!']);
});

Create a middleware.

<?php

declare(strict_types=1);

namespace App\Http\Middleware;

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RequestPayload
{
    public function handle(Request $request, Closure $next)
    {
        var_dump($request->route()->getController());
        return $next($request);
    }
}

Introduce middleware in app/Http/Kernel.php.

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array<int, class-string|string>
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\RequestPayload::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array<string, class-string|string>
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \App\Http\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}

Then when the request is made, an error is reported.

str_contains(): Argument #1 ($haystack) must be of type string, Closure given {"exception":"[object] (TypeError(code: 0): str_contains(): Argument #1 ($haystack) must be of type string, Closure given at /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Support/Str.php:242)
[stacktrace]
#0 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Support/Str.php(242): str_contains()
#1 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Support/Str.php(693): Illuminate\\Support\\Str::contains()
#2 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Route.php(307): Illuminate\\Support\\Str::parseCallback()
#3 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Route.php(287): Illuminate\\Routing\\Route->parseControllerCallback()
#4 /mnt/hgfs/www/laravel/laravel9/app/Http/Middleware/RequestPayload.php(16): Illuminate\\Routing\\Route->getControllerClass()
#5 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): App\\Http\\Middleware\\RequestPayload->handle()
#6 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#7 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()
#8 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#9 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#10 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#11 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#12 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#13 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#14 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Session\\Middleware\\StartSession->handle()
#15 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#16 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#17 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#18 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#19 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#20 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Router.php(799): Illuminate\\Pipeline\\Pipeline->then()
#21 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Router.php(776): Illuminate\\Routing\\Router->runRouteWithinStack()
#22 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Router.php(740): Illuminate\\Routing\\Router->runRoute()
#23 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Routing/Router.php(729): Illuminate\\Routing\\Router->dispatchToRoute()
#24 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(190): Illuminate\\Routing\\Router->dispatch()
#25 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#26 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#27 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#28 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()
#29 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#30 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#31 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#32 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#33 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#34 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#35 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#36 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#37 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Http\\Middleware\\HandleCors->handle()
#38 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#39 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#40 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#41 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(165): Illuminate\\Pipeline\\Pipeline->then()
#42 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(134): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#43 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/octane/src/ApplicationGateway.php(37): Illuminate\\Foundation\\Http\\Kernel->handle()
#44 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/octane/src/Worker.php(92): Laravel\\Octane\\ApplicationGateway->handle()
#45 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/octane/bin/swoole-server(118): Laravel\\Octane\\Worker->handle()
#46 [internal function]: {closure}()
#47 /mnt/hgfs/www/laravel/laravel9/vendor/laravel/octane/bin/swoole-server(164): Swoole\\Server->start()
#48 {main}
driesvints commented 1 year ago

I'm not sure what you expect here? You're trying to retrieve a controller from a route that doesn't uses one?