我运行了一个聊天服务器,它使用Atmosphere作为websocket支持的框架。Atmosphere使用Jersey是因为我使用atmosphere jersey maven依赖项。
聊天服务器在Tomcat7上运行,我们正在升级到Tomcat8。
我们的一个客户使用Tyrus作为他们的Java websocket API。
当我们的聊天服务器部署在Tomcat7(使用Java6、7或8)上时,没有问题。
在Tomcat8 (Java 8)上使用我们的聊天服务器时,使用Atmosphere的测试客户端工作得很好,但是使用Tyrus的客户端就不行了。我们看到的错误是:
2017-01-17 02:36:51,114 ERROR () [http-nio-8443-exec-11] ReflectorServletProcessor (?) - onRequest()
java.lang.IllegalArgumentException: Schema specific part is opaque
at com.sun.jersey.api.uri.UriBuilderImpl.checkSsp(UriBuilderImpl.java:529)
at com.sun.jersey.api.uri.UriBuilderImpl.replacePath(UriBuilderImpl.java:256)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:703)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.atmosphere.util.AtmosphereFilterChain.doFilter(AtmosphereFilterChain.java:135)
at org.atmosphere.util.AtmosphereFilterChain.invokeFilterChain(AtmosphereFilterChain.java:96)
at org.atmosphere.handler.ReflectorServletProcessor$FilterChainServletWrapper.service(ReflectorServletProcessor.java:317)
at org.atmosphere.handler.ReflectorServletProcessor.onRequest(ReflectorServletProcessor.java:160)
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:199)
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:107)
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:66)
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2078)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:571)
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:333)
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:328)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:525)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:428)
at org.atmosphere.container.JSR356Endpoint$1.onMessage(JSR356Endpoint.java:213)
at org.atmosphere.container.JSR356Endpoint$1.onMessage(JSR356Endpoint.java:210)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:393)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:494)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:60)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:183)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:669)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)这是因为在Tomcat7中,来自websocket请求的请求URL类似于"http:// localhost:8080/chat/“(向ws://localhost:8080/chat/发出请求,但它已更改为http://某处)。但是在Tomcat8中,来自websocket请求的请求URL类似于"/chat/“,模式不在那里,Jersey抛出一个错误。
为了解决这个问题,Atmosphere在Atmosphere客户端发出请求时查找报头"origin“,它具有模式。但是当Tyrus客户端发出请求时,"origin“报头不包括http schema,从而导致上面显示的错误。
我想知道是否有人对此有任何简单的解决方案,或者遇到过类似的问题。我已经做了很多寻找一个简单的解决方案,但还没有找到一个。如果没有一个,我们将不得不停止使用are,而使用其他一些东西,这就是大量的代码重构。
这些是关于这个问题的一些票证/错误的链接,似乎已经解决了这个问题,但我有正确的版本,仍然有问题。
https://bz.apache.org/bugzilla/show_bug.cgi?id=56573 https://github.com/Atmosphere/atmosphere/issues/1839
Atmosphere版本: 2.4.8
泽西版本(通过大气):1.19
Tyrus版本: 1.13
发布于 2017-01-25 23:07:41
此问题的解决方法是通过过滤器更改"origin“标头,如果http://模式不存在,则添加它。这篇文章帮助我们解决了这个问题:Modify request parameter with servlet filter
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import javax.servlet.*;
public class FixSchemaFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
chain.doFilter(new FixSchemaHttpServletRequest((HttpServletRequest) request), response);
} else {
chain.doFilter(request, response);
}
}
public class FixSchemaHttpServletRequest extends HttpServletRequestWrapper {
public FixSchemaHttpServletRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getHeader(String header) {
String value = super.getHeader(header);
if (header.equalsIgnoreCase("origin") && !value.startsWith("http://")) {
return "http://" + value;
}
return value;
}
@Override
public Enumeration getHeaders(String header) {
Enumeration enumeration = super.getHeaders(header);
if (header.equalsIgnoreCase("origin") && super.getHeader(header) != null && !super.getHeader(header).startsWith("http://")) {
return Collections.enumeration(Collections.singleton(getHeader(header)));
}
return enumeration;
}
}
}然后将过滤器添加到web.xml
<filter>
<filter-name>FixSchemaFilter</filter-name>
<filter-class>com.example.FixSchemaFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FixSchemaFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>https://stackoverflow.com/questions/41769097
复制相似问题