Bug 60617 - WsWebSocketContainer generates bad CONNECT request when proxy is used
Summary: WsWebSocketContainer generates bad CONNECT request when proxy is used
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: WebSocket (show other bugs)
Version: 8.5.x-trunk
Hardware: All All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
Depends on:
Reported: 2017-01-20 14:00 UTC by Svetlin Zarev
Modified: 2017-01-24 20:24 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
Description Svetlin Zarev 2017-01-20 14:00:08 UTC
Issue Description

WsWebSocketContainer generates bad CONNECT request when a proxy is used. The host does not contain port information, hence the app cannot connect to wss:// endpoints. Also some stricter proxy servers may reject requests without port info, thus making WsWebSocketContainer.connectToServer() fail for both ws:// and wss:// endpoints.

Steps to reproduce

1. Download Tomcat 8.5.9
2. Configure it to use port 8081
3. Clone git@github.com:adamfisk/LittleProxy.git
4. Clone MCVE: git@github.com:SvetlinZarev/websocket-tomcat-bug.git
5. Build (3), (4) -> mvn clean install (you may want to rename the mcve to ROOT)

You can use any other proxy if you already have one.

How to reproduce it
1. Start LittleProxy (it defaults to port 8080)
2. Configure Tomcat use the proxy: export CATALINA_OPTS="-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8080 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8080"
3. Start tomcat: catalina.sh run
4. Request the mcve: http://localhost:8081/ws

Expected behavior
You should see: 

Connected. Sending message...
Message: Hello World!

Actual behavior
An exception is thrown. In case of LittleProxy it is a timeout exception during channel.handshake().get(); In my other case it is a DeploymentException caused by a bad request, because the (stricter) proxy rejected the request because  it does not contain port info.

Additional information
You can play with the mcve by adding the following request parameters:
* scheme - i.e. ws://, wss://
* server - i.e. echo.websocket.org
Request the mcve with: http://localhost:8081/ws?scheme=wss://&server=echo.websocket.org:443

It will succeed. Now remove the port from the server string. It will fail.


According to rfc2817 section 5.2:

    A CONNECT method requests that a proxy establish a tunnel connection on its behalf. The Request-URI portion of the Request-Line is always an 'authority' as defined by URI Generic Syntax [2], which is to say the host name and port number destination of the requested connection separated by a colon

Also by the never finalized draft https://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01#section-3.1:

    The client connects to the proxy server, and uses the CONNECT method to specify the hostname and the port number to connect to. The hostname and port number are separated by a colon, and both of them must be specified
Comment 1 Konstantin Kolinko 2017-01-21 10:44:31 UTC
Pull request: https://github.com/apache/tomcat/pull/39
Comment 2 Mark Thomas 2017-01-24 20:24:54 UTC
Thanks for the patch.

Fixed in:
- trunk for 9.0.0.M18 onwards
- 8.5.x for 8.5.12 onwards
- 8.0.x for 8.0.42 onwards
- 7.0.x for 7.0.76 onwards