WebSocket 握手期间出错(意外响应代码:400)
Error during WebSocket handshake (Unexpected response code: 400)
我的代码在 localhost 中完美运行,但是当我将我的应用程序用于服务器时,这个错误发生了。
WebSocket connection to
'wss://url.com/webSocket/193/uj4s3xue/websocket' failed: Error during
WebSocket handshake: Unexpected response code: 400
sockjs.min.js:2 POST
https://url.com/webSocket/193/e1vwalij/xhr_streaming?t=1495418202369
403 (Forbidden)
Js 代码:
function connect() {
var socket = new SockJS('/webSocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.debug = null;
stompClient.subscribe('/topic/messages/' + vm.id, function (greeting) {
refreshMessages(JSON.parse(greeting.body));
});
});
}
Java 代码:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/webSocket").setAllowedOrigins("*").withSockJS();
}
@Bean
public PresenceChannelInterceptor presenceChannelInterceptor() {
return new PresenceChannelInterceptor();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(presenceChannelInterceptor());
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.taskExecutor().corePoolSize(8);
registration.setInterceptors(presenceChannelInterceptor());
}
}
在 spring 服务器中发生以下异常:
2017-05-27 11:14:57.101 ERROR 51230 --- [ XNIO-2 task-11]
o.s.w.s.s.s.DefaultHandshakeHandler : Handshake failed due to
invalid Upgrade header: null
2017-05-27 11:16:10.020 ERROR 51230 --- [MessageBroker-1]
o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred
in scheduled task.
org.springframework.web.socket.sockjs.SockJsTransportFailureException:
Failed to write SockJsFrame content='h'; nested exception is
java.io.IOException: Broken pipe at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:339)
at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.sendHeartbeat(AbstractSockJsSession.java:255)
at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession$HeartbeatTask.run(AbstractSockJsSession.java:451)
at
org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266) at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748) Caused by:
java.io.IOException: Broken pipe at
sun.nio.ch.FileDispatcherImpl.writev0(Native Method) at
sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:51) at
sun.nio.ch.IOUtil.write(IOUtil.java:148) at
sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:504) at
org.xnio.nio.NioSocketConduit.write(NioSocketConduit.java:161) at
io.undertow.server.protocol.http.HttpResponseConduit.write(HttpResponseConduit.java:645)
at
io.undertow.conduits.ChunkedStreamSinkConduit.doWrite(ChunkedStreamSinkConduit.java:163)
at
io.undertow.conduits.ChunkedStreamSinkConduit.write(ChunkedStreamSinkConduit.java:127)
at
org.xnio.conduits.ConduitStreamSinkChannel.write(ConduitStreamSinkChannel.java:150)
at
io.undertow.channels.DetachableStreamSinkChannel.write(DetachableStreamSinkChannel.java:240)
at
io.undertow.server.HttpServerExchange$WriteDispatchChannel.write(HttpServerExchange.java:2049)
at
io.undertow.servlet.spec.ServletOutputStreamImpl.writeBufferBlocking(ServletOutputStreamImpl.java:570)
at
io.undertow.servlet.spec.ServletOutputStreamImpl.flushInternal(ServletOutputStreamImpl.java:485)
at
io.undertow.servlet.spec.ServletOutputStreamImpl.flush(ServletOutputStreamImpl.java:472)
at
io.undertow.servlet.spec.HttpServletResponseImpl.flushBuffer(HttpServletResponseImpl.java:461)
at
javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215)
at
javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215)
at
org.springframework.security.web.util.OnCommittedResponseWrapper.flushBuffer(OnCommittedResponseWrapper.java:159)
at
javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215)
at
org.springframework.http.server.ServletServerHttpResponse.flush(ServletServerHttpResponse.java:96)
at
org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.writeFrameInternal(AbstractHttpSockJsSession.java:350)
at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:322)
... 10 common frames omitted
服务器是 apache2 网络服务器。我该如何解决这个问题?
我通过用
激活 ws_tunnel 来解决这个问题
sudo a2enmod proxy_wstunnel
并使 RewriteEngine On apache 000-default-le-ssl.conf
文件位于
/etc/apache2/sites-enabled/000-default-le-ssl.conf
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /webSocket(.*) ws://127.0.0.1:8080/webSocket/ [P,L]
我的代码在 localhost 中完美运行,但是当我将我的应用程序用于服务器时,这个错误发生了。
WebSocket connection to 'wss://url.com/webSocket/193/uj4s3xue/websocket' failed: Error during WebSocket handshake: Unexpected response code: 400
sockjs.min.js:2 POST https://url.com/webSocket/193/e1vwalij/xhr_streaming?t=1495418202369 403 (Forbidden)
Js 代码:
function connect() {
var socket = new SockJS('/webSocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.debug = null;
stompClient.subscribe('/topic/messages/' + vm.id, function (greeting) {
refreshMessages(JSON.parse(greeting.body));
});
});
}
Java 代码:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/webSocket").setAllowedOrigins("*").withSockJS();
}
@Bean
public PresenceChannelInterceptor presenceChannelInterceptor() {
return new PresenceChannelInterceptor();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(presenceChannelInterceptor());
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.taskExecutor().corePoolSize(8);
registration.setInterceptors(presenceChannelInterceptor());
}
}
在 spring 服务器中发生以下异常:
2017-05-27 11:14:57.101 ERROR 51230 --- [ XNIO-2 task-11] o.s.w.s.s.s.DefaultHandshakeHandler : Handshake failed due to invalid Upgrade header: null
2017-05-27 11:16:10.020 ERROR 51230 --- [MessageBroker-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
org.springframework.web.socket.sockjs.SockJsTransportFailureException: Failed to write SockJsFrame content='h'; nested exception is java.io.IOException: Broken pipe at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:339) at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.sendHeartbeat(AbstractSockJsSession.java:255) at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession$HeartbeatTask.run(AbstractSockJsSession.java:451) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:748) Caused by: java.io.IOException: Broken pipe at sun.nio.ch.FileDispatcherImpl.writev0(Native Method) at sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:51) at sun.nio.ch.IOUtil.write(IOUtil.java:148) at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:504) at org.xnio.nio.NioSocketConduit.write(NioSocketConduit.java:161) at io.undertow.server.protocol.http.HttpResponseConduit.write(HttpResponseConduit.java:645) at io.undertow.conduits.ChunkedStreamSinkConduit.doWrite(ChunkedStreamSinkConduit.java:163) at io.undertow.conduits.ChunkedStreamSinkConduit.write(ChunkedStreamSinkConduit.java:127) at org.xnio.conduits.ConduitStreamSinkChannel.write(ConduitStreamSinkChannel.java:150) at io.undertow.channels.DetachableStreamSinkChannel.write(DetachableStreamSinkChannel.java:240) at io.undertow.server.HttpServerExchange$WriteDispatchChannel.write(HttpServerExchange.java:2049) at io.undertow.servlet.spec.ServletOutputStreamImpl.writeBufferBlocking(ServletOutputStreamImpl.java:570) at io.undertow.servlet.spec.ServletOutputStreamImpl.flushInternal(ServletOutputStreamImpl.java:485) at io.undertow.servlet.spec.ServletOutputStreamImpl.flush(ServletOutputStreamImpl.java:472) at io.undertow.servlet.spec.HttpServletResponseImpl.flushBuffer(HttpServletResponseImpl.java:461) at javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215) at javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215) at org.springframework.security.web.util.OnCommittedResponseWrapper.flushBuffer(OnCommittedResponseWrapper.java:159) at javax.servlet.ServletResponseWrapper.flushBuffer(ServletResponseWrapper.java:215) at org.springframework.http.server.ServletServerHttpResponse.flush(ServletServerHttpResponse.java:96) at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.writeFrameInternal(AbstractHttpSockJsSession.java:350) at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:322) ... 10 common frames omitted
服务器是 apache2 网络服务器。我该如何解决这个问题?
我通过用
激活 ws_tunnel 来解决这个问题sudo a2enmod proxy_wstunnel
并使 RewriteEngine On apache 000-default-le-ssl.conf
文件位于
/etc/apache2/sites-enabled/000-default-le-ssl.conf
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /webSocket(.*) ws://127.0.0.1:8080/webSocket/ [P,L]