You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony+Mercure与Angular16的SSE订阅认证问题求助

解决Angular 16订阅Mercure SSE的认证问题及ngx-sse-client参数不匹配问题

一、修复ngx-sse-client参数不匹配问题

  • 检查安装版本:本地包与GitHub源码参数不一致,大概率是安装的版本非最新版,先确认当前版本:
    npm list ngx-sse-client
    
  • 升级到最新版:
    npm install ngx-sse-client@latest
    
  • 按当前版本类型定义调用:若升级后仍为2个参数,说明当前版本stream方法通过第二个参数传递配置(包含headers),示例代码:
    import { SseClient } from 'ngx-sse-client';
    
    constructor(private sseClient: SseClient) {}
    
    subscribeToMercure() {
      const authToken = 'your-jwt-token';
      this.sseClient.stream('/mercure', {
        headers: {
          'Authorization': `Bearer ${authToken}`
        }
      }).subscribe({
        next: (event) => {
          // 触发前端缓存刷新逻辑
          console.log('收到Mercure事件:', event);
        },
        error: (err) => console.error('SSE订阅出错:', err)
      });
    }
    

二、替代方案:自定义SSE服务(无需第三方库)

原生EventSource不支持自定义请求头,但可通过XMLHttpRequest模拟SSE,实现带认证头的订阅:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class MercureSseService {
  subscribe(url: string, authToken: string): Observable<string> {
    return new Observable(observer => {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.setRequestHeader('Authorization', `Bearer ${authToken}`);
      xhr.setRequestHeader('Accept', 'text/event-stream');
      xhr.setRequestHeader('Cache-Control', 'no-cache');

      let lastPosition = 0;
      xhr.onprogress = () => {
        if (xhr.responseText) {
          const newData = xhr.responseText.slice(lastPosition);
          lastPosition = xhr.responseText.length;
          // 解析SSE格式数据
          const events = newData.split('\n\n').filter(line => line.trim());
          events.forEach(event => {
            const dataMatch = event.match(/^data:\s*(.*)$/m);
            if (dataMatch) {
              observer.next(dataMatch[1]);
            }
          });
        }
      };

      xhr.onerror = (error) => observer.error(error);
      xhr.onload = () => observer.complete();

      xhr.send();
      return () => xhr.abort();
    });
  }
}

使用示例:

constructor(private mercureSse: MercureSseService) {}

refreshCacheOnUpdate() {
  const mercureUrl = 'https://your-caddy-mercure-endpoint/.well-known/mercure';
  const token = 'your-auth-token';
  this.mercureSse.subscribe(mercureUrl, token).subscribe({
    next: (data) => {
      // 执行缓存刷新操作,比如重新获取内容
      console.log('收到更新通知,刷新缓存:', data);
    }
  });
}

三、Mercure认证的其他注意事项

  • URL参数传递token:若不想自定义请求头,可将认证token放在URL参数中(Mercure支持mercureAuthorization参数),示例:
    const mercureUrl = `https://your-caddy-mercure-endpoint/.well-known/mercure?mercureAuthorization=Bearer ${token}`;
    // 用原生EventSource订阅
    const eventSource = new EventSource(mercureUrl);
    eventSource.onmessage = (event) => { /* 处理事件 */ };
    
  • CORS配置:确保Caddy的Mercure插件允许前端域名跨域请求,且允许携带认证头或Credentials,Caddyfile配置示例:
    your-domain.com {
      mercure {
        publish *
        subscribe *
        cors origin https://your-angular-app.com
        allow-credentials
      }
    }
    

内容的提问来源于stack exchange,提问作者AntiFTW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:20:25