Webman使用阿里云SLB存在跨域问题

Tinywan

阿里云SLB配置

跨域截图

官方中间件也使用了

https://www.workerman.net/doc/webman/middleware.html

middleware.php 配置

return [
    '' => [
        \app\middleware\AccessControlMiddleware::class,
    ]
];

AccessControlMiddleware

declare(strict_types=1);

namespace app\middleware;

use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;

class AccessControlMiddleware implements MiddlewareInterface
{
    /**
     * @param Request $request
     * @param callable $next
     * @return Response
     */
    public function process(Request $request, callable $next): Response
    {
        $response = $request->method() == 'OPTIONS' ? response('') : $next($request);
        $response->withHeaders([
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With,Origin',
            'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS',
        ]);
        return $response;
    }
}

调试

var_dump(11111111111111);
$response = $request->method() == 'OPTIONS' ? response('') : $next($request);
var_dump(222222222222222);

使用Postman请求有打印

前端(Vue)请求没有任何打印信息

3084 2 0
2个回答

walkor

是不是设置了路由,路由用any,不要用post,跨域请求可能有options请求,只设置post路由会导致跨域出现问题。

  • Tinywan 2021-12-15

    post 修改成any 就可以了

  • walkor 2021-12-15

    跨域的接口用Route::any()或者 Route::add(['POST', 'OPTIONS'])

  • Tinywan 2021-12-15

    谢谢老大,我这边尝试一下

  • Tinywan 2021-12-17

    这个路由会有一个问题,如果POST和PUT路径一样,同时使用 Route::add(['POST', 'OPTIONS'] 和 Route::add(['GET', 'OPTIONS'] ,系统会提示:FastRoute\BadRouteException: Cannot register two routes matching "/console/resources/(\d+)" for method "OPTIONS" in /vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php:111

  • walkor 2021-12-17

    Route::add(['POST', 'PUT', 'OPTIONS']); 放一起

  • Tinywan 2021-12-17

    我这个多条路由

    Route::group('/resources', function () {
        Route::get('', [ConsoleResource::class, 'getList']);
        Route::add(['POST', 'OPTIONS'],'', [ConsoleResource::class, 'create']);
        Route::put('/{id:\d+}', [ConsoleResource::class, 'update']);
        Route::delete('/{id:\d+}', [ConsoleResource::class, 'delete']);
        Route::add(['GET', 'OPTIONS'],'/{id:\d+}', [ConsoleResource::class, 'detail']);
        Route::add(['POST', 'OPTIONS'],'/{id:\d+}/authorize', [ConsoleResource::class, 'authorizeApi']);
    });
  • Tinywan 2021-12-17

    上面的路由 Route::put('/{id:\d+}', [ConsoleResource::class, 'update']); 由于这个正则 {id:\d+} 也跨域了

  • lscho 2021-12-17

    单独在/resources 这个分组下面注册一个OPTIONS类型,匹配所有请求就可以了。OPTIONS请求的作用只是预检而已。

  • Tinywan 2021-12-17

    直接放在全局就也是可以的

    // 匹配所有options路由
    Route::options('[{path:.+}]', function (){
    return response('');
    });

  • walkor 2021-12-17

    如果一个uri的put get post等需要单独的action处理的,lscho 给的方案是正解,单独设置一个options路由。

    Route::group('/resources', function () {
        // 匹配 /resources 下的所有options路由
        Route::options('[{path:.+}]', function (){
            return response('');
        })->middleware([\app\middleware\跨域中间件类名::class]);
        // ........
    });
Maoxp

补充一句: 如果没有使用route路由,跨域的话,可以参考

  • 暂无评论
年代过于久远,无法发表回答
🔝