Skip to content

Fix #188 Clarify the interaction of upgrade with Servlet specification #415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions spec/src/main/asciidoc/WebSocket.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,67 @@ excluding certain JAR files from the scan (see Servlet 3.0, section
containing many JAR files that the developer knows do not contain any
WebSocket endpoints._

[[interaction-of-http-upgrade-to-websocket-with-the-servlet-api]]
==== Interaction of HTTP upgrade to WebSocket with the Servlet API

HTTP upgrade requests for WebSockets are mapped to **Filter**s and a *Servlet*
using the standard Servlet specification request mapping rules.

The WebSocket upgrade process behaves as if it is implemented as a *Filter* in
the *FilterChain* and may, but is not required to be, implemented as such. The
remainder of this section is written as if the WebSocket upgrade process has
been implemented as a *Filter*. If the WebSocket upgrade process has not been
implemented as a *Filter*, additional container specific configuration may be
required.

The WebSocket upgrade *Filter* is positioned in the *FilterChain* after any
**Filter**s defined in the deployment descriptor (*web.xml*). Applications
requiring that the WebSocket upgrade *Filter* is positioned earlier in the
*FilterChain* may define it explicitly in the deployment descriptor.
Comment on lines +1294 to +1297
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server defined and implemented Filter should be after Server filters and before deployment descriptor filters, not after.

  1. Server Filters (there are many examples of this: CORS, Forwarding, Security features that don't fit into Servlet Securtity, Auditing, GZIP, etc)
  2. WebSocket Filter
  3. Deployment Descriptor (web.xml and annotations from webapp)


*Filter* instances earlier in the *FilterChain* may manipulate and/or wrap the
request and/or response and these behaviours may influence the functionality of
the WebSocket upgrade *Filter*. Developers should be aware that some *Filter*
implementations may not have considered HTTP upgrade and configuring such
**Filter**s before the WebSocket upgrade *Filter* in the *FilterChain* may break
the HTTP upgrade process.
Comment on lines +1299 to +1304
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the websocket server implementation supplied WebSocket as a Filter unwrap and requests or responses before it upgrades? (I say yes)


If the response passed to the *doFilter()* method of the WebSocket upgrade
*Filter* has been committed, then the WebSocket upgrade *Filter* will take no
further action and pass the request and response to the next *Filter* in the
*FilterChain*.
Comment on lines +1306 to +1309
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good addition. 👍


If the response passed to the *doFilter()* method of the WebSocket upgrade
*Filter* has not been committed and the WebSocket upgrade *Filter* determines
that the criteria have been met to allow the upgrade to WebSocket to proceed,
then the response will be reset before the WebSocket upgrade *Filter* writes the
appropriate response headers and status code.
Comment on lines +1311 to +1315
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a duplicate of the paragraph immediately above this.


Applications that require a greater degree of control over the HTTP upgrade
process should use *WsServerContainer.upgradeHttpToWebSocket* method to manually
trigger the HTTP upgrade process to WebSocket. Such applications will probably
wish to avoid the use of WebSocket annotations so that the container does not
automatically deploy WebSocket endpoints as described in
<<application-deployment-on-web-containers>>.
Comment on lines +1317 to +1322
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get a ServletContext attribute that disables/configures specific jakarta.websocket features?

  1. WebSocket Upgrade as a Filter from implementation (options: enable/disable, default is enabled)
  2. WebSocket Upgrade as a Filter location (options: before/after deployment descriptor from webapp, default is before)

I could see some attributes to disable automatic endpoint additions too.
This would be useful for some scenarios.
There's also the scanning of the webapp to support jakarta.websocket.server.ServerApplicationConfig features.

  1. Scan and deploy annotated endpoints.
  2. Scan and report to ServletApplicationConfig entries.


By default, the WebSocket upgrade *Filter* is mapped to the dispatch types
`REQUEST` and `FORWARD`.

The concatenation of `servletPath` and `pathInfo` (`pathInfo` is ignored if it
is `null`) must be used to match the HTTP upgrade request to a registered
WebSocket endpoint as per <<uri-mapping>>. Only HTTP upgrade requests that match
a registered WebSocket endpoint are handled by the WebSocket upgrade *Filter*.
All other requests are passed to the next *Filter* in the *FilterChain*.

If the HTTP upgrade request is processed by the WebSocket upgrade *Filter* but
does not result in a successful upgrade to the WebSocket protocol, a suitable
status code must be set on the HTTP response and the response committed. The
HTTP upgrade request is not passed to the next *Filter* in the *FilterChain*.

*ServletRequestListener* instances are called for the WebSocket upgrade process
in the same way as for any other request/response (i.e. before the HTTP upgrade
request processing enters the *FilterChain* and after it exits).

[[application-deployment-in-standalone-websocket-server-containers]]
=== Application Deployment in Standalone WebSocket Server Containers

Expand Down Expand Up @@ -1516,6 +1577,10 @@ This appendix is non-normative.
* https://github.com/jakartaee/websocket/issues/176[Issue 176]
Clarify the responsibilities for sending ping messages.

* https://github.com/jakartaee/websocket/issues/188[Issue 188]
Clarify the interaction of the HTTP upgrade to WebSocket with Filters, Listeners
and RequestDispatchers when deployed on a Servlet container.

=== Changes Between 2.1 and 2.0

* https://github.com/eclipse-ee4j/websocket-api/issues/190[Issue 190] and
Expand Down