繁体   English   中英

无法获取服务器发送的事件和事件源以在JHipster中工作

[英]Can't get server sent events and event source to work in JHipster

我正在将JHipster 3.5.0与spring-boot和angular一起使用来构建应用程序。 我想使用服务器发送的事件将更新从后端发送到UI,但是无法正常工作。

这是我的RestController的代码:

@RestController
@RequestMapping("/api")
public class SSEResource {
    private final List<SseEmitter> sseEmitters = new CopyOnWriteArrayList<>();

    @RequestMapping(value = "/sse", method = RequestMethod.GET)
    @Timed
    public SseEmitter getSSE() throws IOException {
        SseEmitter sseEmitter = new SseEmitter();
        this.sseEmitters.add(sseEmitter);
        sseEmitter.send("Connected");
        return sseEmitter;
    }

    @Scheduled(fixedDelay = 3000L)
    public void update() {
        this.sseEmitters.forEach(emitter -> {
            try {
                emitter.send(String.valueOf(System.currentTimeMillis()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}

我的Angaluar控制器如下所示:

(function () {
    'use strict';

    angular
        .module('myApp')
        .controller('SSEController', SSEController);

    SSEController.$inject = [];

    function SSEController() {
        var vm = this;            

        vm.msg = {};

        function handleCallback(msg) {
            vm.msg = msg.data;
        }

        vm.source = new EventSource('api/sse');
        vm.source.addEventListener('message', handleCallback, false);
    }
})
();

当我尝试使用该代码时,会收到一个

406不可接受的HTTP状态

由于请求标头Accept:“ text / event-stream” 如果我手动将标头更改为接受:“ / *”,然后使用浏览器的调试工具重播该请求,则会得到

401未经授权的HTTP状态

我想我缺少了一些非常简单的东西,但是我已经检查了我的SecurityConfiguration和authInterceptor而不了解丢失了什么。

有人可以解释我在做什么错吗?

要回答我自己的问题:解决方案确实非常简单,也确实不满意:

我正在将Jhipster与JWT身份验证结合使用,该身份验证依赖于HTTP标头“身份验证”。 EventSource不支持标题! 看到

解决方案可能是使用支持标题的polyfill。 我通过此事件源polyfill的提交成功地测试了它并支持标题

(function () {
    'use strict';

    angular
        .module('myApp')
        .controller('SSEController', SSEController);

    SSEController.$inject = ['$scope', 'AuthServerProvider'];

    function SSEController($scope, AuthServerProvider) {
        var vm = this;            

        vm.msg = {};

        var options = {
            headers : {
                Authorization : "Bearer " + AuthServerProvider.getToken()
            }
        }

        vm.source = new EventSource('api/sse', options);
        vm.source.addEventListener('message', handleCallback, false);
    }
})
();

由于某些原因,标头支持不再包含在master分支或原始polyfill中。 因此,我不确定这是否是正确的方法。 我可能会切换到websockets。

编辑:我想我找到了一种使用标准EventSource的方法。 JWTFilter类包含一种从请求参数中检索访问令牌的方法。 所以我可以像这样使用EventSource:

source = new EventSource('api/sse?access_token=' + AuthServerProvider.getToken());

如此轻松,以至于让我有些尴尬,以至于我以前从未见过。

在@Jan答案的基础上,这是我如何修改JWTFilter.resolveToken方法以使其看起来像这样:

文件 :java / myapp / security / jwt / JWTFilter.java

    private String resolveToken(HttpServletRequest request){
        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7, bearerToken.length());
        }
        // pick token as GET parameter
        bearerToken = request.getParameter("access_token");
        return bearerToken;
   }

在前端,这是我使用的相关代码:

    this.eventSource = new EventSource('api/screens/sse?access_token=' + this.authServer.getToken());
    this.eventSource.addEventListener('message', evt => {
        const messageEvent = evt as MessageEvent;
        this._alarmCount = parseInt(messageEvent.data, 10);
    });
    this.eventSource.onerror = evt => {
        console.log('EventSource error' + evt.data);
    };

最后,我不得不修改rest控制器以清理完成的发射器:

 public SseEmitter getSSE() throws IOException {
    SseEmitter sseEmitter = new SseEmitter();
    synchronized (this) {
        this.sseEmitters.add(sseEmitter);
    }
    sseEmitter.onCompletion(() -> {
        synchronized (this) {
            // clean up completed emitters
            this.sseEmitters.remove(sseEmitter);
        }
    });
    sseEmitter.send(String.valueOf(System.currentTimeMillis()));
    return sseEmitter;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM