Reputation: 765
Is this possible to serve websocket handler and normal servlet over same context?
Sample
http://localhost/appcontext/endpoint --> serving by normal servlet
ws://localhost/appcontext/endpoint --> serving by websocket handler
I have tried multiple ways but can't able to do it. It seem url mapping is filtered by the context path and not by the protocol like 'http' or 'ws'. May be what I found is wrong. I was trying to see this using spring and java.
Upvotes: 0
Views: 1450
Reputation: 3412
Nope, you cannot use the same path served either by servlet or websocket. Each http request to http://localhost/appcontext/endpoint
is expected to have a specific behaviour
This answer goes out of Java scope as it mainly relies on RFC 6455, aka the websocket bible. The reason why lies in the handshake process.
Websocket URIs
In section 3 of RFC 6455, the websocket URI is defined as followed:
ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
Leaving the URI details aside, one might actually thinks that it is possible to solely access the HTTP counterpart with only HTTP protocol.
The handshake: client side
Reminder: websocket is a bidirectional protocol. Consequently, the client is the entity which initialises the connection. However, once the connection is established, both client and server can send a message or closes the communication. But the server and client concept is kept to know who is who
The client initialises the handshake: "Hey server! I want to establish a webosocket communication". However, the handshake starts over http. On page 17 of RFC 6455 (section 4.1):
The handshake MUST be a valid HTTP request as specified by [RFC2616].
The method of the request MUST be GET, and the HTTP version MUST be at least 1.1.
For example, if the WebSocket URI is "ws://example.com/chat", the first line sent should be "GET /chat HTTP/1.1".
The "Request-URI" part of the request MUST match the /resource name/ defined in Section 3 (a relative URI) or be an absolute http/https URI that, when parsed, has a /resource name/, /host/, and /port/ that match the corresponding ws/wss URI.
Behind every websocket communication initialisation hides an HTTP request of the same path. To get back to your example:
ws://localhost/appcontext/endpoint
http://localhost/appcontext/endpoint
with an upgrade request and the appropriate headers defined by RFC 6455http(s)
to ws(s)
The handshake: server side
But what if you want to cheat and say "I pretend I don't know that this is a websocket URI and I want to access the HTTP resources behind this URL". On the server-side, your application had registered a path http://localhost/appcontext/endpoint
for URI matching as "I'm waiting websocket connections here", similarly to web services path matching process. In section 4.2.1 of RFC 6455:
The client’s opening handshake consists of the following parts. If the server, while reading the handshake, finds that the client did not send a handshake that matches the description below (note that as per [RFC2616], the order of the header fields is not important), including but not limited to any violations of the ABNF grammar specified for the components of the handshake, the server MUST stop processing the client’s handshake and return an HTTP response with an appropriate error code (such as 400 Bad Request).
An HTTP/1.1 or higher GET request, including a "Request-URI" [RFC2616] that should be interpreted as a /resource name/ defined in Section 3 (or an absolute HTTP/HTTPS URI containing the /resource name/).
A |Host| header field containing the server’s authority.
An |Upgrade| header field containing the value "websocket", treated as an ASCII case-insensitive value.
As http://localhost/appcontext/endpoint
is registered for websocket handshake, a basic HTTP request does not include the Upgrade
header and is then rejected by the server.
While writing this answer, I tried it with:
appcontext/endpoint
appcontext/endpoint/index.xhtml
index.xhtml
: so appcontext/endpoint
redirects to index.xhtml
As expected, my websocket connection fails. If I change the page path from endpoint/index.xhtml
to endpoint2/index.xhtml
, the websocket works back.
However, I just found that http://demos.kaazing.com/echo/ uses the same URL for its websocket connection and I couldn't find why >_<
Upvotes: 3