Skip to main content
added 8 characters in body
Source Link

Will create the pull request to Spring to fix that bughttps://github.com/spring-projects/spring-framework/pull/28000

Will create the pull request to Spring to fix that bug

added 1442 characters in body
Source Link
XhrReceiver.prototype._chunkHandler = function(status, text) { debug('_chunkHandler', status); if (status !== 200 || !text) { return; } for (var idx = -1; ; this.bufferPosition += idx + 1) { var buf = text.slice(this.bufferPosition); idx = buf.indexOf('\n'); if (idx === -1) { break; } var msg = buf.slice(0, idx); if (msg) { debug('message', msg); this.emit('message', msg); } } }; 
XhrReceiver.prototype._chunkHandler = function(status, text) { debug('_chunkHandler', status); if (status !== 200 || !text) { return; } for (var idx = -1; ; this.bufferPosition += idx + 1) { var buf = text.slice(this.bufferPosition); idx = buf.indexOf('\n'); if (idx === -1) { break; } var msg = buf.slice(0, idx); if (msg) { debug('message', msg); this.emit('message', msg); } } }; 

But in case of "Connection already closed (but not removed yet) forsessionId" Spring Framework sends justunformatted SockJsFrame.closeFrameGoAway() without ending \n.

AbstractHttpSendingTransportHandler.class

 protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response, AbstractHttpSockJsSession sockJsSession) throws SockJsException { if (sockJsSession.isNew()) { if (logger.isDebugEnabled()) { logger.debug(request.getMethod() + " " + request.getURI()); } sockJsSession.handleInitialRequest(request, response, getFrameFormat(request)); } else if (sockJsSession.isClosed()) { if (logger.isDebugEnabled()) { logger.debug("Connection already closed (but not removed yet) for " + sockJsSession); } SockJsFrame frame = SockJsFrame.closeFrameGoAway(); try { response.getBody().write(frame.getContentBytes()); } catch (IOException ex) { throw new SockJsException("Failed to send " + frame, sockJsSession.getId(), ex); } } 

SockJsFrame

without ending \n.

I`veAs a quick and dirty fix I just created copy of org.springframework.web.socket.sockjs.frame.SockJsFrame and put in my classpath to substitute the original file with modified one.

public static SockJsFrame closeFrame(int code, @Nullable String reason) { return new SockJsFrame("c[" + code + ",\"" + (reason != null ? reason : "") + "\"]\n"); } 

But in reality AbstractHttpSendingTransportHandler class should be fixed to apply format to the SockJS frame.

SockJsFrameFormat frameFormat = this.getFrameFormat(request); SockJsFrame frame = SockJsFrame.closeFrameGoAway(); String formattedFrame = frameFormat.format(frame); try { response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET)); } 

Without that fix message is not parsed as close message.

Will create the pull request to Spring to fix that bug

XhrReceiver.prototype._chunkHandler = function(status, text) { debug('_chunkHandler', status); if (status !== 200 || !text) { return; } for (var idx = -1; ; this.bufferPosition += idx + 1) { var buf = text.slice(this.bufferPosition); idx = buf.indexOf('\n'); if (idx === -1) { break; } var msg = buf.slice(0, idx); if (msg) { debug('message', msg); this.emit('message', msg); } } }; 

But Spring Framework sends just

without ending \n.

I`ve just created copy of org.springframework.web.socket.sockjs.frame.SockJsFrame and put in my classpath to substitute the original file with modified one.

public static SockJsFrame closeFrame(int code, @Nullable String reason) { return new SockJsFrame("c[" + code + ",\"" + (reason != null ? reason : "") + "\"]\n"); } 

Without that fix message is not parsed as close message.

XhrReceiver.prototype._chunkHandler = function(status, text) { debug('_chunkHandler', status); if (status !== 200 || !text) { return; } for (var idx = -1; ; this.bufferPosition += idx + 1) { var buf = text.slice(this.bufferPosition); idx = buf.indexOf('\n'); if (idx === -1) { break; } var msg = buf.slice(0, idx); if (msg) { debug('message', msg); this.emit('message', msg); } } }; 

But in case of "Connection already closed (but not removed yet) forsessionId" Spring Framework sends unformatted SockJsFrame.closeFrameGoAway() without ending \n.

AbstractHttpSendingTransportHandler.class

 protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response, AbstractHttpSockJsSession sockJsSession) throws SockJsException { if (sockJsSession.isNew()) { if (logger.isDebugEnabled()) { logger.debug(request.getMethod() + " " + request.getURI()); } sockJsSession.handleInitialRequest(request, response, getFrameFormat(request)); } else if (sockJsSession.isClosed()) { if (logger.isDebugEnabled()) { logger.debug("Connection already closed (but not removed yet) for " + sockJsSession); } SockJsFrame frame = SockJsFrame.closeFrameGoAway(); try { response.getBody().write(frame.getContentBytes()); } catch (IOException ex) { throw new SockJsException("Failed to send " + frame, sockJsSession.getId(), ex); } } 

SockJsFrame

As a quick and dirty fix I just created copy of org.springframework.web.socket.sockjs.frame.SockJsFrame and put in my classpath to substitute the original file with modified one.

public static SockJsFrame closeFrame(int code, @Nullable String reason) { return new SockJsFrame("c[" + code + ",\"" + (reason != null ? reason : "") + "\"]\n"); } 

But in reality AbstractHttpSendingTransportHandler class should be fixed to apply format to the SockJS frame.

SockJsFrameFormat frameFormat = this.getFrameFormat(request); SockJsFrame frame = SockJsFrame.closeFrameGoAway(); String formattedFrame = frameFormat.format(frame); try { response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET)); } 

Without that fix message is not parsed as close message.

Will create the pull request to Spring to fix that bug

Source Link

I spent a lot of time debugging SockJS and Spring code to figure out with that issue and what I have found.

xhr.js file has next method to parse inbound text message:

XhrReceiver.prototype._chunkHandler = function(status, text) { debug('_chunkHandler', status); if (status !== 200 || !text) { return; } for (var idx = -1; ; this.bufferPosition += idx + 1) { var buf = text.slice(this.bufferPosition); idx = buf.indexOf('\n'); if (idx === -1) { break; } var msg = buf.slice(0, idx); if (msg) { debug('message', msg); this.emit('message', msg); } } }; 

That method expects \n at the end of the SockJS text frame.

But Spring Framework sends just

public static SockJsFrame closeFrame(int code, @Nullable String reason) { return new SockJsFrame("c[" + code + ",\"" + (reason != null ? reason : "") + "\"]"); } 

without ending \n.

I`ve just created copy of org.springframework.web.socket.sockjs.frame.SockJsFrame and put in my classpath to substitute the original file with modified one.

public static SockJsFrame closeFrame(int code, @Nullable String reason) { return new SockJsFrame("c[" + code + ",\"" + (reason != null ? reason : "") + "\"]\n"); } 

After that fix all works as expected and c[1000, "Go Away!"] successfully routes to the 'c' section of next switch

SockJS.prototype._transportMessage = function(msg) { ... switch (type) { case 'a': if (Array.isArray(payload)) { payload.forEach(function(p) { debug('message', self.transport, p); self.dispatchEvent(new TransportMessageEvent(p)); }); } break; case 'm': debug('message', this.transport, payload); this.dispatchEvent(new TransportMessageEvent(payload)); break; case 'c': if (Array.isArray(payload) && payload.length === 2) { this._close(payload[0], payload[1], true); } break; } }; 

Without that fix message is not parsed as close message.