hyperf跨域问题

ops/2025/3/16 5:38:21/

2024年4月25日10:11:30

前段时间写完了hyperf的cms之后,回头写hyperf的一些文章或者笔记,发现hyperf和laravel真的很像,又有swoole的协程使用,真的很舒服,还有微服务。

官方推荐的是方式就是使用中间件,但是注意,你在路由上使用的时候,中间件是无法实现跨域的,因为在路由组件会抛出一个HttpException,请求OPTIONS返回405状态码。

方案一:
https://hyperf.wiki/3.1/#/zh-cn/middleware/middleware?id=%e8%b7%a8%e5%9f%9f%e4%b8%ad%e9%97%b4%e4%bb%b6

<?phpdeclare(strict_types=1);namespace App\Middleware;use Hyperf\Context\Context;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;class CorsMiddleware implements MiddlewareInterface
{public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{$response = Context::get(ResponseInterface::class);$response = $response->withHeader('Access-Control-Allow-Origin', '*')->withHeader('Access-Control-Allow-Credentials', 'true')->withHeader('Access-Control-Allow-Methods', '*')->withHeader('Access-Control-Allow-Headers', '*');Context::set(ResponseInterface::class, $response);if ($request->getMethod() == 'OPTIONS') {return $response->withStatus(204)->withBody(new SwooleStream(''));}return $handler->handle($request);}
}

新建一个CorsMiddleware 放在hyperf/config/autoload/middlewares.php的里面加入中间件

方案二:在nginx的反向代理利加入跨域配置

location / {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods *;add_header Access-Control-Allow-Headers *;if ($request_method = 'OPTIONS') {return 204;}
}

方案三:如果你现在路由上使用跨域中间件
新建一个hyperf/app/Exception/Handler/HttpExceptionHandler.php
把文件加入到 hyperf/config/autoload/exceptions.php

declare(strict_types=1);
/*** This file is part of Hyperf.** @link     https://www.hyperf.io* @document https://hyperf.wiki* @contact  group@hyperf.io* @license  https://github.com/hyperf/hyperf/blob/master/LICENSE*/
return ['handler' => ['http' => [Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
//            App\Exception\Handler\HttpExceptionHandler::class,App\Exception\Handler\AppExceptionHandler::class,],],
];

替换Hyperf的Handler

declare(strict_types=1);namespace App\Exception\Handler;use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
use Hyperf\HttpMessage\Exception\HttpException;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Swow\Psr7\Message\ResponsePlusInterface;
use Throwable;class HttpExceptionHandler extends ExceptionHandler
{public function __construct(protected StdoutLoggerInterface $logger, protected FormatterInterface $formatter){}/*** Handle the exception, and return the specified result.* @param HttpException $throwable*/public function handle(Throwable $throwable, ResponsePlusInterface $response){$this->logger->debug($this->formatter->format($throwable));$this->stopPropagation();$request = Context::get(ServerRequestInterface::class);if ($request->getMethod() == 'OPTIONS') {return $response->setStatus(204)->withHeader('Access-Control-Allow-Origin', '*')->withHeader('Access-Control-Allow-Credentials', 'true')->withHeader('Access-Control-Allow-Headers', '*')->withHeader('Access-Control-Allow-Methods', '*')->setBody(new SwooleStream(''));}return $response->setStatus($throwable->getStatusCode())->setBody(new SwooleStream($throwable->getMessage()));}/*** Determine if the current exception handler should handle the exception.** @return bool If return true, then this exception handler will handle the exception,*              If return false, then delegate to next handler*/public function isValid(Throwable $throwable): bool{return $throwable instanceof HttpException;}
}

这里稍微改一下也可以实现跨域

方案四:在路由上加上OPTIONS,也是需要配合中间件跨域,才能使用的,这样就可以在路由上使用跨域中间件

Router::addGroup('/api/admin', function () {Router::post('/login', [\App\Controller\Admin\IndexController::class, 'login']);Router::post('/getCaptcha', [\App\Controller\Admin\IndexController::class, 'getCaptcha']);Router::post('/uploadPic', [\App\Controller\Admin\IndexController::class, 'uploadPic']);Router::post('/uploadFile', [\App\Controller\Admin\IndexController::class, 'uploadFile']);
});改成:
Router::addRoute(['OPTIONS', 'POST'],'/login',  [\App\Controller\Admin\IndexController::class, 'login']);
虽然看起来有点不舒服,但是也是一个很好方案

个人建议是第一种,简单方便


http://www.ppmy.cn/ops/27429.html

相关文章

【Vue 2.x】学习vue之三路由

文章目录 Vue三路由第十章1、vue中的路由vue的应用分为a、多页面应用b、单页面应用 2、路由的基本应用1、基础2、使用3、加载 3、vue组件的分类1、普通组件2、路由组件 4、路由的嵌套5、路由传递Query参数1、拼接参数传递2、路由传递对象 6、简化路由1、命名路由 7、parms传递参…

Wpf DataGrid ComboBox 列

遇到的问题 最开始找到的例子要写 Convert, 感觉和 Vue-Elment 的差别比较大后面找到类似与 Vue-Element UI 的写法&#xff0c;开始时数值不更新 关键代码 <DataGridTemplateColumn Header"Digit" Width"100"><DataGridTemplateColumn.CellTem…

spring boot应用停止服务需要注意的地方

Spring Boot应用实现优雅停服的关键在于确保在服务关闭之前能够完成以下几点&#xff1a; 处理完所有已接收的请求&#xff1a;确保正在处理的请求能够正常完成&#xff0c;避免数据丢失或不一致。拒绝新的请求&#xff1a;一旦开始关闭流程&#xff0c;应该立即停止接收新的外…

PHP源码_最新在线工具箱网站系统源码

项目运行截图 源码贡献 https://githubs.xyz/boot?app41 部分数据库表 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for toolbox_category -- ---------------------------- DROP TABLE IF EXISTS toolbox_category…

方法学习后简单案例

方法简单案例 案例1&#xff1a;键盘录入一个数据n(1<n<9)&#xff0c;输出对应的nn乘法表 import java.util.Scanner; public class Test{public static void main(String[] args){Scanner scan new Scanner(System.in);System.out.println("请输入1~9的数字&…

神经网络的反向传播

梯度下降算法 &#x1f525;我们来看一下神经网络中的梯度下降算法&#x1f525; 梯度下降法是一种优化算法&#xff0c;用于寻找目标函数的最小值。梯度是一个向量&#xff0c;表示某一函数在该点处的方向导数沿着该方向取得最大值&#xff0c;即函数在该点处变化最快的方向…

Java 长字符串拼接性能优化

文章目录 引言I values 值拼接II RestController 返回参数不需要手动转JSON字符串III 多语句执行(allowMultiQueries=true)3.1 需求:通过XML手动拼接SQL实现多值插入3.2 案例引言 批量新增数据( values 值拼接 )RestController 返回参数不需要手动转JSON字符串。I values …

每天五分钟深度学习:如何理解梯度下降算法可以逼近全局最小值?

本文重点 上节课程中,我们已经知道了逻辑回归的代价函数J。要想最小化代价函数,我们需要使用梯度下降算法。 梯度下降算法地直观理解: 为了可视化,我们假设w和b都是单一实数,实际上,w可以是更高地维度。 代价函数J是在水平轴w和b上的曲面,因此曲面的高度就是J(w,b)在…