jiannei / laravel-response

🤖 Provide a standardized and unified response data structure for Laravel and Lumen API projects. - 为 Laravel 和 Lumen API 项目提供一个规范统一的响应数据结构。
MIT License
240 stars 30 forks source link

配置API限流,请求超过限制后, 响应方式为视图 #111

Open HelplessMan opened 10 months ago

HelplessMan commented 10 months ago

laravel version: 10.28.0

大致配置:

config/response.php

....

    'exception' => [
        \Illuminate\Validation\ValidationException::class => [
            'code' => 422,
        ],
        \Illuminate\Auth\AuthenticationException::class => [

        ],
        \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class =>[
            'message' => '',
        ],
        \Illuminate\Database\Eloquent\ModelNotFoundException::class => [
            'message' => '',
        ],
       // 在这里新增了一个API限流异常
        \Illuminate\Http\Exceptions\ThrottleRequestsException::class => [
            'code' => 429,
            'message' => 'Too Many Requests'
        ],
    ],

....

加了一个 Accept App\Http\Middleware\AcceptHeader.php


<?php

namespace App\Http\Middleware;

use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response;

class AcceptHeader { /**


> App\Http\Kernel.php

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,
    ],

    'api' => [
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
       \App\Http\Middleware\AcceptHeader::class
        //\App\Http\Middleware\ListenerHttpRequest::class
    ],
];

然后看源码 怀疑还是 `Accept`没有生效?没办法,目前在`App\Exceptions\Handle.php`增加了一个 `render`方法
public function render($request, Throwable $exception)
{

// if ($exception instanceof ThrottleRequestsException) { // return Response::fail($exception->getMessage(), 429); // } return $this->prepareJsonResponse($request, $exception); }



但是目前这样子的话。在访问API超过限制(1分钟5次请求) 后, 直接以浏览器方式请求的话 显示如下:
<img width="1173" alt="image" src="https://github.com/jiannei/laravel-response/assets/9101275/a9dc0584-4632-4193-a1e5-99dd3d451e83">

如果是用API工具发起请求。 会出现请求阻塞。一直到超过限流时间的同时获取到数据.....
HelplessMan commented 10 months ago

现在好想找到原因了, 不需要 render ....

\App\Http\Middleware\AcceptHeader::class$middlewareGroups.api 的位置移动到 $middleware 这里就可以了...

这是什么原因呢?

jiannei commented 5 months ago

出现问题的原因可能是部分路由请求不符合 $request->expectsJson()

// vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php
protected function renderExceptionResponse($request, Throwable $e)
{
    return $this->shouldReturnJson($request, $e)
                ? $this->prepareJsonResponse($request, $e)
                : $this->prepareResponse($request, $e);
}

// vendor/laravel/framework/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php
public function expectsJson()
{
    return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
}

AcceptHeader$middleware中,相当于让所有路由请求都成了 api 请求,可以按这思路检查下