簡體   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