From 7367610f5cd6057966cc17742f41d5ef204095c7 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Thu, 29 Jun 2023 09:12:44 +0100 Subject: [PATCH 1/2] Fix #188 Clarify the interaction of upgrade with Servlet specification Includes how the HTTP upgrade to WebSocket interacts with: - Filters; - Listeners; and - RequestDispatchers when running on a Servlet container --- spec/src/main/asciidoc/WebSocket.adoc | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/spec/src/main/asciidoc/WebSocket.adoc b/spec/src/main/asciidoc/WebSocket.adoc index 1a05677e..ab61e6a3 100644 --- a/spec/src/main/asciidoc/WebSocket.adoc +++ b/spec/src/main/asciidoc/WebSocket.adoc @@ -1278,6 +1278,43 @@ 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-websocket-endpoints-with-servlet-mappings]] +=== Interaction of WebSocket endpoints with Servlet mappings + +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 position of the WebSocket upgrade *Filter* in the *FilterChain* is +configured using the standard Filter ordering rules of the Servlet +specification. *Filter* instances earlier in the *FilterChain* may wrap the +request and/or response and these wrappers will be visible to, and may +influence, the WebSocket upgrade *Filter*. + +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 <>. 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 @@ -1516,6 +1553,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 From fe2d871d9045d470851de1d76ef1f0413aae7328 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Mon, 20 Nov 2023 11:44:21 +0000 Subject: [PATCH 2/2] Updates in light of review comments --- spec/src/main/asciidoc/WebSocket.adoc | 38 ++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/spec/src/main/asciidoc/WebSocket.adoc b/spec/src/main/asciidoc/WebSocket.adoc index ab61e6a3..754bfc15 100644 --- a/spec/src/main/asciidoc/WebSocket.adoc +++ b/spec/src/main/asciidoc/WebSocket.adoc @@ -1278,8 +1278,8 @@ 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-websocket-endpoints-with-servlet-mappings]] -=== Interaction of WebSocket endpoints with Servlet mappings +[[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. @@ -1291,11 +1291,35 @@ 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 position of the WebSocket upgrade *Filter* in the *FilterChain* is -configured using the standard Filter ordering rules of the Servlet -specification. *Filter* instances earlier in the *FilterChain* may wrap the -request and/or response and these wrappers will be visible to, and may -influence, the WebSocket upgrade *Filter*. +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. + +*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. + +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*. + +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. + +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 +<>. By default, the WebSocket upgrade *Filter* is mapped to the dispatch types `REQUEST` and `FORWARD`.