WebSocket - 无效的状态行 javascript

WebSocket - Invalid status line javascript

我是 运行 weblogic 12.1.3 服务器上的 spring 3.1.2 后端。 为了接受 websocket 连接,我的配置器如下:

public class SpringConfigurator extends Configurator {

    private static final Logger LOGGER = LoggerFactory.make();

    private static final Map<String, Map<Class<?>, String>> cache = new ConcurrentHashMap<String, Map<Class<?>, String>>();

    private static final String MAGIC_STR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    private static final String NO_VALUE = ObjectUtils.identityToString(new Object());

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {

        WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
        if (wac == null) {
            String message = "Failed to find the root WebApplicationContext. Was ContextLoaderListener not used?";
            LOGGER.error(message);
            throw new IllegalStateException(message);
        }

        String beanName = ClassUtils.getShortNameAsProperty(endpointClass);
        if (wac.containsBean(beanName)) {
            T endpoint = wac.getBean(beanName, endpointClass);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Using @ServerEndpoint singleton " + endpoint);
            }
            return endpoint;
        }

        Component annot = AnnotationUtils.findAnnotation(endpointClass, Component.class);
        if ((annot != null) && wac.containsBean(annot.value())) {
            T endpoint = wac.getBean(annot.value(), endpointClass);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Using @ServerEndpoint singleton " + endpoint);
            }
            return endpoint;
        }

        beanName = getBeanNameByType(wac, endpointClass);
        if (beanName != null) {
            return (T) wac.getBean(beanName);
        }

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Creating new @ServerEndpoint instance of type " + endpointClass);
        }
        return wac.getAutowireCapableBeanFactory().createBean(endpointClass);
    }

    // modifyHandshake() is called before getEndpointInstance()
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        super.modifyHandshake(sec, request, response);

    }

    private String getBeanNameByType(WebApplicationContext wac, Class<?> endpointClass) {

        String wacId = wac.getId();

        Map<Class<?>, String> beanNamesByType = cache.get(wacId);
        if (beanNamesByType == null) {
            beanNamesByType = new ConcurrentHashMap<Class<?>, String>();
            cache.put(wacId, beanNamesByType);
        }

        if (!beanNamesByType.containsKey(endpointClass)) {
            String[] names = wac.getBeanNamesForType(endpointClass);
            if (names.length == 1) {
                beanNamesByType.put(endpointClass, names[0]);
            } else {
                beanNamesByType.put(endpointClass, NO_VALUE);
                if (names.length > 1) {
                    String message = "Found multiple @ServerEndpoint's of type " + endpointClass + ", names=" + names;
                    LOGGER.error(message);
                    throw new IllegalStateException(message);
                }
            }
        }

        String beanName = beanNamesByType.get(endpointClass);
        return NO_VALUE.equals(beanName) ? null : beanName;
    }

}

问题是当我尝试通过 javascript 客户端打开 websocket 连接时,它会正确生成响应 headers 因为我调试了这个位置:

@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
    super.modifyHandshake(sec, request, response);
}

但在客户端出现以下错误:

WebSocket connection to 'ws://localhost:7001/websocket' failed: Error during >WebSocket handshake: Invalid status line

在 chrome 开发人员工具中,响应如下所示:

HTTP/0.9 200 OK

我觉得 http 请求没有升级到 websocket 连接。

非常感谢有关此问题的任何帮助。

我今天在 WebLogic 12.2.1 上测试 http://showcase.omnifaces.org/push/socket 时遇到了这个问题。

webapp 的第一次测试尝试中,WebLogic 在建立 websocket 连接时抛出了以下异常:

java.lang.IllegalStateException: The async-support is disabled on this request: weblogic.servlet.internal.ServletRequest
Impl@6682044b[GET /omnifaces.push/counter?e6845a3a-26ed-4520-9824-63ffd85b24eb HTTP/1.1]
    at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:1949)
    at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:1925)
    at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432)
    at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:234)
    ...

事实证明,与我测试的all other servers相反,WebLogic自带的TyrusServletFilter,负责处理websocket握手请求,内部安装after[=36] =] 通过部署的 webapp 的 web.xml 提供的过滤器。 webapp 附带了一个字符编码过滤器和一个映射到 /* 的 GZIP 过滤器,因此它们在 websocket 过滤器之前被调用。乍一看这很奇怪,但我认为它就是这样,所以我只是将 <async-supported>true</async-supported> 添加到那些 webapp 提供的过滤器中,以便 TyrusServletFilter 可以完成它的工作。

但是,在建立 websocket 连接时,Java客户端在发送推送消息时发生脚本错误,正是您遇到的消息:

WebSocket connection to 'ws://localhost:7001/omnifaces.push/counter?e6845a3a-26ed-4520-9824-63ffd85b24eb' failed: Error during WebSocket handshake: Invalid status line

事实证明,WebSockets 无法处理 GZIP 响应。禁用 GZIP 过滤器后,一切继续完美运行。

然而,根本问题是 WebLogic 应该在 所有 webapp 提供的过滤器之前安装它的 TyrusServletFilter 。我测试过的所有其他 Java EE 服务器都正确地做到了这一点。正如您对问题的评论中提到的,您立即将所有 websocket 握手请求发送和转发到它们的目标 URL 模式的解决方法是一个很好的解决方法。另一种方法是重新配置 web.xml 提供的过滤器,使其不再匹配 websocket 握手请求,例如通过使用更具体的 URL 模式,或改为映射到特定的 servlet。