2017-01-20 14 views
0

Я запускаю сервер чата, который использует Atmosphere в качестве основы для поддержки websocket. Атмосфера использует Джерси, потому что я использую зависимость от атмосферы-Джерси.Ошибка Атмосфера + Джерси с клиентом Tomcat 8 и не-Атмосфера

Сервер чата работает на Tomcat 7 и мы обновление до Tomcat 8.

Один из наших клиентов использует в качестве Тира Java WebSocket API.

Когда наш чат-сервер развернут на Tomcat 7 (с Java 6,7 ​​или 8), проблем нет.

С нашим чат-сервером на Tomcat 8 (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) 

Это происходит потому, что с Tomcat 7, запрос URL из запроса WebSocket рассматривается как аналог «HTTP: // локальный: 8080/чат /» (сделан запрос to ws: // localhost: 8080/chat/но он изменен на http: // где-то). Но с Tomcat 8 URL-адрес запроса из запроса websocket похож на «/ chat /», а схемы там нет, и Джерси вызывает ошибку.

Для борьбы с этим Атмосфера ищет заголовок «origin», который имеет схему, когда клиент Atmosphere делает запрос. Но когда клиент Tyrus делает запрос, этот заголовок «origin» не включает http-схему, в результате которой появляется ошибка, показанная выше.

Мне интересно, есть ли у кого-нибудь идеи для простого решения этой проблемы или возникли аналогичные проблемы. Я много искал простое решение, но еще не нашел его. Без этого мы пытаемся прекратить использование Atmosphere и использовать что-то еще, что много рефакторинга кода.

Это некоторые ссылки на билет/ошибки вокруг этой проблемы, которые, казалось бы, были адресованы этому, но у меня есть правильные версии и все еще есть проблемы.

https://bz.apache.org/bugzilla/show_bug.cgi?id=56573 https://github.com/Atmosphere/atmosphere/issues/1839

версия Атмосфера: 2.4.8

Джерси версия (через атмосферу): 1,19

Тир версия: 1.13

ответ

0

Обойти это было изменяют " 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>