Search code examples
javaapachetomcatwebsocketjava-websocket

Websocket Apache 2.4.x Proxy Tomcat 7.x open event happens only on browser side


I programmed a chat app using javascript on browser side and server endpoint programmed with javax.websocket api. I first tested the app by establishing connection between browser and tomcat and everything worked fine (OS is Windows 7).

When I tried to use a apache 2.4.18 server as a proxy reverse over ssl it seems that the connection gets not completely established and I only get an onopen event on the browser.
My tomcat log tells me, that the server endpoint instance also is created, but the onopen event doesn't happen on the server endpoint instance. It seems to me that the server endpoint listens on the wrong port or something like this.

I use an ajp connector on the tomcat side. I tried to solve the problem or get an idea where it could fail, but with no success.

Here are my code snippets:

Chrome-Network-Log:

enter image description here

Chrome-Javascript-console:

controller_chat.js:1952 chatBuildWSLink
controller_chat.js:1960 wsLink: wss://x:443/myapp/chat
controller_chat.js:343 chatCheckConnection
controller_chat.js:345 connect
controller_chat.js:313 Connecting to wss://x:443/myapp/chat
controller_chat.js:353 wsServerOnOpen
controller_chat.js:363 wsServerOnMessage
controller_chat.js:411 wsServerOnError
controller_chat.js:422 wsServerOnClose
controller_chat.js:228 chatCreateMenuBar
controller_chat.js:5 chatCreateTable
controller_chat.js:5 chatCreateTable
controller_chat.js:5 chatCreateTable
controller_chat.js:5 chatCreateTable
controller_chat.js:355 onopen Event: {"isTrusted":true}
controller_chat.js:356 onopen Event-Code: undefined
controller_chat.js:357 onopen Event-Reason: undefined
controller_chat.js:358 onopen Event-WasClean: undefined

My apache httpd-conf:

LoadModule proxy_module modules/mod_proxy.so                            
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule ssl_module modules/mod_ssl.so

ProxyPass /myapp/chat/ wss://x:443/myapp/chat 
ProxyPassReverse /myapp/chat/ wss://x:443/myapp/chat 

ProxyPass /myapp/ ajp://x:8009/myapp/
ProxyPassReverse /eProjectCare/ ajp://x:8009/myapp/

NameVirtualHost myhost
<VirtualHost myhost:443>

  ...
  DocumentRoot "c:/Apache24/htdocs"
  ServerName myhost
  ServerAdmin admin@example.com
  SSLEngine on
  SSLProxyEngine on
  SSLCertificateFile "c:/OpenSSL-Win64/bin/chat.crt"
  SSLCertificateKeyFile "c:/OpenSSL-Win64/bin/chat.key"

...
</VirtualHost>

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 1000

My Tomcat-Log:

09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.checkOrigin , originHeaderValue: https://myhost
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.checkOrigin checkOrigin: true
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getNegotiatedSubprotocol , getNegotiatedSubprotocol: 
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getNegotiatedSubprotocol, negotiated Subprotocoll:  
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getNegotiatedExtensions , getNegotiatedExtensions: 
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getNegotiatedExtensions, negotiatedExtensions: permessage-deflate
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getNegotiatedExtensions NegotiatedExtensions: [org.apache.tomcat.websocket.WsExtension@28130514]
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.modifyHandshake , modifyHandshake: 
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.modifyHandshake , HttpSession: org.apache.catalina.session.StandardSessionFacade@3fbf9eec
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.modifyHandshake , csrfsession: 5e7f914546aef5bf389472c86b67234c1e68dc1e
09:39:50.756 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.modifyHandshake , csrfrequest: 
09:39:50.758 [ajp-bio-8009-exec-2] DEBUG admin (3/1) SecurityService.readUser: Benutzer 3 wird aus der Datenbank gelesen ...
09:39:50.759 [ajp-bio-8009-exec-2] DEBUG admin (3/1) DatabaseService.closeConnection: schliesse Connection fuer: <.getLiveUser:> (1137989066)
09:39:50.759 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.modifyHandshake , userProperties for ServerEndpointConfig set...: {}
09:39:50.759 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getEndpointInstance , getEndpointInstance: 
09:39:50.759 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer Erstelle Endpoint-Instanz!
09:39:50.759 [ajp-bio-8009-exec-2] DEBUG admin (3/1) ChatServer.getEndpointInstance Endpoint-Instance: de.pmgnet.eprojectcare.websocket.chat.chatserver.ChatServer@3f39a0a

Normally after that, the onopen event happens in my server-endpoint.class and gets logged, but this only happens if I establish the connection without proxy to tomcat...

This is my first question on stackoverflow, so please be patient with me, if I forgot some important information in my subscription. Would be nice if anyone has a suggestion. Thx!


Solution

  • for all that maybe struggle with the same topic, after a lot of fetching through websites and reading, i found a solution and will make a conclusion for all that are interested.

    AJP-Connector:

    AJP - connector of tomcat 7 does not! support websocket but it also does not give any logs or errors, see also this: 1: https://mail-archives.apache.org/mod_mbox/tomcat-users/201408.mbo x/%3C53FF3A3A.3040507@christopherschultz.net%3E

    So for websocket i used the https - connector, that already comes with the server.xml of apache tomcat:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
                   maxThreads="150" SSLEnabled="true" scheme="https"      secure="true"
                   keystoreFile="E:\ssl\mykeystore" keystorePass="315225"    keyPass="315225"
                   clientAuth="false" sslProtocol="TLS" />
    

    I defined a selfsigned certificate regarding to the article of bob: enter link description here

    > httdp.conf

    I changed the ports in the httpd.conf to fit with the proxypass:

    ProxyPass /myapp/chat wss://myhost:8443/myapp/chat
    ProxyPassReverse /myapp/chat wss://myhost:8443/myapp/chat
    
    ProxyPass /myapp/ https://myhost:8443/myapp/
    ProxyPassReverse /myapp/ https://myhost:8443/myapp/
    

    Well, this was ending in an Proxy-Error caused by the self-signed-certificate of the tomcat. For testing and development you can avoid this with a few additional rows in the httpd.conf:

    <IfModule ssl_module>
    SSLRandomSeed startup builtin
    SSLRandomSeed connect builtin
    SSLProxyEngine on
    SSLProxyVerify none 
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off
    </IfModule> 
    

    The last thing for me to solve, was to choose the right dependency in my pom.xml for the websocket, depending on the tomcat-version, it can be found on maven-repository: enter link description here and should look like this:

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-websocket</artifactId>
        <version>7.0.64</version>
    </dependency>
    

    Don't use the javax.websocket dependency, even with the <scope>provided</scope> attribute it didn't work for me (maybe i did something wrong or forgot something)

    Hope this works and helps you guys:-)