如何使用nestjs反向代理sse请求

问题描述 投票:0回答:1

我有一个外部 Web 应用程序,它有后端 (nodeJs) 和客户端 (Vue)。 现在我们想在反向代理后面使用这个 Web 应用程序(不是 Nginx,因为我们实现了一个内部逻辑来绕过一些逻辑)。

我们发现应用程序正在使用 sse 来更新 UI,因此现在我们还应该支持 sse 代理请求。我们使用 NestJs 来代理所有有效的 http 请求,现在我们陷入了 sse 请求。

这就是我们实现

sse
控制器的方式

@Sse('/rest/push')
  async proxyPushMessages(@Res({ passthrough: true }) response: FastifyReply, @Req() request: any) {
    const sseStream = this.sseProxyService.proxySSE(request);
    response.header('Content-Type', 'text/event-stream');
    response.header('Cache-Control', 'no-cache');
    response.header('Connection', 'keep-alive');
    sseStream.subscribe(
      (messageEvent) => {
        return response.send(`data: ${messageEvent.data}`);
      },
      (error) => {
        console.error('SSE Error:', error);
        return response.send(`data: ${error}`);
      },
      () => {
        return response.send(`data: ${'SSE stream closed'}`);
      },
    );
  }

这是 sse 代理服务,它将请求代理到应用程序后端

import { map, Observable } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { FastifyRequest, Injectable } from '@transmit-security/bindid-services-core-service';
import { AxiosRequestConfig } from 'axios';
const baseWorkflowsUrl = process.env.WORKFLOWS_SERVER_URL || 'http://localhost:5678';

@Injectable()
export class SSEProxyService {
  constructor(private httpService: HttpService) {}
  private buildUrl(url: string): string {
    return `${baseWorkflowsUrl}${url}`;
  }
  proxySSE(req: FastifyRequest): Observable<MessageEvent> {
    const { url, method, headers } = req;
    const reqObject: AxiosRequestConfig = {
      url: this.buildUrl(url),
      withCredentials: true,
      responseType: 'text',
      method,
      headers: headers as any,
    };
    return this.httpService.request(reqObject).pipe(map((response) => new MessageEvent('message', response.data)));
  }
}

看起来推送请求已解决,但用户界面仍然没有更新。 我缺少什么?

附浏览器网络快照

nestjs reverse-proxy server-sent-events
1个回答
0
投票

最终我通过使用

http-proxy-middleware
npm lib 在幕后处理它来解决它。 代码示例

    this.proxy = createProxyMiddleware({
      target: process.env.WORKFLOWS_SERVER_URL,
      secure: false,
      ws: true,
      onProxyRes: (proxyRes: any, req: any, res: any) => {
        res.setHeader(
          'Content-Security-Policy',
          `default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self' ${process.env.WORKFLOWS_SERVER_URL} 'unsafe-inline' 'unsafe-eval' ;script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests`,
        );
      },
    });
  }
© www.soinside.com 2019 - 2024. All rights reserved.