rkljw 4 месяцев назад
Родитель
Сommit
e79f7b80af
3 измененных файлов с 96 добавлено и 0 удалено
  1. 47 0
      app/Controller/SseController.php
  2. 39 0
      app/Service/Server/StreamServer.php
  3. 10 0
      config/autoload/cors.php

+ 47 - 0
app/Controller/SseController.php

@@ -0,0 +1,47 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Controller;
+
+use Hyperf\HttpServer\Contract\RequestInterface;
+use Hyperf\HttpServer\Contract\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+
+class SseController extends AbstractController
+{
+    public function stream(RequestInterface $request, ResponseInterface $response)
+    {
+        var_dump("===");
+        // 设置响应头
+        $response = $response
+            ->withAddedHeader('Access-Control-Allow-Origin', '*') // 确保允许跨域
+            ->withAddedHeader('Access-Control-Allow-Methods', 'GET')
+            ->withAddedHeader('Content-Type', 'text/event-stream')
+            ->withAddedHeader('Cache-Control', 'no-cache')
+            ->withAddedHeader('Connection', 'keep-alive');
+        var_dump("bbbbbbb");
+        $origin = $request->getHeaderLine('Origin');
+        if ($this->isAllowedOrigin($origin)) {
+            var_dump("nicde");
+            $response = $response->withAddedHeader('Access-Control-Allow-Origin', $origin);
+            $response = $response->withAddedHeader('Access-Control-Allow-Credentials', 'true');
+        }
+        // 开始流式传输
+        $this->container->get(\Swoole\Http\Response::class)->status(200);
+        for ($i = 0; $i < 10; $i++) { // 模拟发送10个事件
+            $data = json_encode(['message' => "Event $i"]);
+            var_dump("测试数据");
+            $response->write("data: $data\n\n");
+            usleep(1000000); // 暂停1秒
+        }
+        return $response;
+    }
+    protected function isAllowedOrigin(string $origin): bool
+    {
+        // 实现你的逻辑来判断是否允许该来源
+        // 可以是硬编码的值,也可以是从数据库或其他地方获取的动态值
+        $allowedOrigins = ['http://localhost:3000', 'http://192.168.1.100:3000']; // 替换为你的前端地址
+
+        return in_array($origin, $allowedOrigins, true);
+    }
+}

+ 39 - 0
app/Service/Server/StreamServer.php

@@ -0,0 +1,39 @@
+<?php
+
+
+namespace App\Service\Server;
+
+
+use Hyperf\Dispatcher\HttpDispatcher;
+use Hyperf\ExceptionHandler\ExceptionHandlerDispatcher;
+use Hyperf\HttpServer\ResponseEmitter;
+use Hyperf\HttpServer\Server;
+use Psr\Container\ContainerInterface;
+use Swoole\Http\Request;
+use Swoole\Http\Response;
+
+class StreamServer extends Server
+{
+    const STREAM_URL = [
+        '/chat/stream'
+    ];
+    public function __construct(ContainerInterface $container, HttpDispatcher $dispatcher, ExceptionHandlerDispatcher $exceptionHandlerDispatcher, ResponseEmitter $responseEmitter)
+    {
+        parent::__construct($container, $dispatcher, $exceptionHandlerDispatcher, $responseEmitter);
+    }
+
+    /**
+     * @param Request $request
+     * @param Response $response
+     */
+    public function onRequest($request, $response): void
+    {
+        $pathInfo = $request->server['path_info'];
+        if (in_array($pathInfo, self::STREAM_URL)) {
+            $response->header('Content-Type', 'text/event-stream');
+            $response->header('Cache-Control', 'no-cache');
+            $response->header('Connection', 'keep-alive');
+        }
+        parent::onRequest($request, $response);
+    }
+}

+ 10 - 0
config/autoload/cors.php

@@ -0,0 +1,10 @@
+<?php
+return [
+    'paths' => ['api/*', 'chat/stream'], // 允许访问的路径
+    'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
+    'allowed_origins' => ['http://localhost:3000', 'http://192.168.1.100:3000'], // 替换为你的前端地址
+    'allowed_headers' => ['Content-Type', 'Authorization'], // 允许的请求头
+    'exposed_headers' => [], // 暴露给前端的响应头
+    'max_age' => 0, // 预检请求的结果可以被缓存的时间
+    'supports_credentials' => false, // 是否支持凭证
+];