Merged branch 'jetty-10.0.x' into 'jetty-11.0.x'.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
commit
38a5d41117
|
@ -209,6 +209,7 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.memcached</groupId>
|
||||
|
@ -225,5 +226,15 @@
|
|||
<artifactId>websocket-jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jakarta-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-websocket-configure-filter]]
|
||||
==== Advanced `WebSocketUpgradeFilter` Configuration
|
||||
|
||||
The `WebSocketUpgradeFilter` that handles the HTTP requests that upgrade to WebSocket is installed in these cases:
|
||||
|
||||
* Either by the `JakartaWebSocketServletContainerInitializer`, as described in xref:pg-server-websocket-standard[this section].
|
||||
* Or by a call to `JettyWebSocketServerContainer.addMapping(\...)`, as described in xref:pg-server-websocket-jetty[this section].
|
||||
|
||||
Typically, the `WebSocketUpgradeFilter` is not present in the `web.xml` configuration, and therefore the mechanisms above create a new `WebSocketUpgradeFilter` and install it _before_ any other Filter declared in `web.xml`, under the default name of `"org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter"` and with path mapping `/*`.
|
||||
|
||||
However, if the `WebSocketUpgradeFilter` is already present in `web.xml` under the default name, then the ``ServletContainerInitializer``s will use that declared in `web.xml` instead of creating a new one.
|
||||
|
||||
This allows you to customize:
|
||||
|
||||
* The filter order; for example, by configuring the `CrossOriginFilter` (or other filters) for increased security or authentication _before_ the `WebSocketUpgradeFilter`.
|
||||
* The `WebSocketUpgradeFilter` configuration via ``init-param``s, that affects all `Session` instances created by this filter.
|
||||
* The `WebSocketUpgradeFilter` path mapping. Rather than the default mapping of `+/*+`, you can map the `WebSocketUpgradeFilter` to a more specific path such as `+/ws/*+`.
|
||||
* The possibility to have multiple ``WebSocketUpgradeFilter``s, mapped to different paths, each with its own configuration.
|
||||
|
||||
For example:
|
||||
|
||||
[source,xml,subs=verbatim]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
|
||||
version="5.0">
|
||||
<display-name>My WebSocket WebApp</display-name>
|
||||
|
||||
<!-- The CrossOriginFilter *must* be the first --> <!--1-->
|
||||
<filter>
|
||||
<filter-name>cross-origin</filter-name>
|
||||
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>cross-origin</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- Configure the default WebSocketUpgradeFilter --> <!--2-->
|
||||
<filter>
|
||||
<!-- The filter name must be the default WebSocketUpgradeFilter name -->
|
||||
<filter-name>org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter</filter-name> <!--3-->
|
||||
<filter-class>org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter</filter-class>
|
||||
<!-- Configure at most 1 MiB text messages -->
|
||||
<init-param> <!--4-->
|
||||
<param-name>maxTextMessageSize</param-name>
|
||||
<param-value>1048576</param-value>
|
||||
</init-param>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter</filter-name>
|
||||
<!-- Use a more specific path mapping for WebSocket requests -->
|
||||
<url-pattern>/ws/*</url-pattern> <!--5-->
|
||||
</filter-mapping>
|
||||
|
||||
</web-app>
|
||||
----
|
||||
<1> The `CrossOriginFilter` is the first to protect against link:https://owasp.org/www-community/attacks/csrf[cross-site request forgery attacks].
|
||||
<2> The configuration for the _default_ `WebSocketUpgradeFilter`.
|
||||
<3> Note the use of the _default_ `WebSocketUpgradeFilter` name.
|
||||
<4> Specific configuration for `WebSocketUpgradeFilter` parameters.
|
||||
<5> Use a more specific path mapping for `WebSocketUpgradeFilter`.
|
||||
|
||||
Note that using a more specific path mapping for WebSocket requests is also beneficial to the performance of normal HTTP requests: they do not go through the `WebSocketUpgradeFilter` (as they will not match its path mapping), saving the cost of analyzing them to see whether they are WebSocket upgrade requests or not.
|
|
@ -0,0 +1,177 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-websocket-jetty]]
|
||||
==== Jetty APIs Implementation
|
||||
|
||||
When you write a WebSocket application using the Jetty WebSocket APIs, your code typically need to depend on just the Jetty WebSocket APIs to compile your application.
|
||||
However, at runtime you need to have the _implementation_ of the Jetty WebSocket APIs in your class-path (or module-path).
|
||||
|
||||
Jetty's WebSocket APIs are provided by the following Maven artifact:
|
||||
|
||||
[source,xml,subs=normal]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jetty-api</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Jetty's implementation of the Jetty WebSocket APIs is provided by the following Maven artifact (and its transitive dependencies):
|
||||
|
||||
[source,xml,subs=normal]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jetty-server</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The `websocket-jetty-api` artifact and the `websocket-jetty-server` artifact (and its transitive dependencies) should be present in the server class-path (or module-path), and never in the web application's `/WEB-INF/lib` directory.
|
||||
====
|
||||
|
||||
To configure correctly your WebSocket application based on the Jetty WebSocket APIs, you need two steps:
|
||||
|
||||
. Make sure that Jetty xref:pg-server-websocket-jetty-container[sets up] an instance of `JettyWebSocketServerContainer`.
|
||||
. Use the `JettyWebSocketServerContainer` APIs in your applications to xref:pg-server-websocket-jetty-endpoints[register your WebSocket endpoints] that implement your application logic.
|
||||
|
||||
[[pg-server-websocket-jetty-container]]
|
||||
===== Setting up `JettyWebSocketServerContainer`
|
||||
|
||||
Jetty sets up a `JettyWebSocketServerContainer` instance using `JettyWebSocketServletContainerInitializer`.
|
||||
|
||||
When you deploy web applications using xref:pg-server-http-handler-use-webapp-context[`WebAppContext`], then `JettyWebSocketServletContainerInitializer` is automatically discovered and initialized by Jetty when the web application starts, so that it sets up the `JettyWebSocketServerContainer`.
|
||||
In this way, you do not need to write any additional code:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardContainerWebAppContext]
|
||||
----
|
||||
|
||||
On the other hand, when you deploy web applications using xref:pg-server-http-handler-use-servlet-context[`ServletContextHandler`], you have to write the code to ensure that the `JettyWebSocketServletContainerInitializer` is initialized, so that it sets up the `JettyWebSocketServerContainer`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyContainerServletContextHandler]
|
||||
----
|
||||
|
||||
Calling `JettyWebSocketServletContainerInitializer.configure(\...)` must be done _before_ the `ServletContextHandler` is started, and configures the Jetty WebSocket implementation for that web application context.
|
||||
|
||||
[[pg-server-websocket-jetty-endpoints]]
|
||||
===== Configuring Endpoints
|
||||
|
||||
Once you have xref:pg-server-websocket-jetty-container[setup] the `JettyWebSocketServerContainer`, you can configure your xref:pg-websocket-endpoints[WebSocket endpoints].
|
||||
|
||||
Differently from the xref:pg-server-websocket-standard-endpoints[configuration of standard WebSocket endpoints], WebSocket endpoint classes may be annotated with Jetty WebSocket API annotations, or extend the `org.eclipse.jetty.websocket.api.WebSocketListener` interface, but they are not automatically discovered, not even when deploying web applications using xref:pg-server-http-handler-use-webapp-context[`WebAppContext`].
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
When using the Jetty WebSocket APIs, WebSocket endpoints must always be explicitly configured.
|
||||
====
|
||||
|
||||
There are two ways of configuring WebSocket endpoints when using the Jetty WebSocket APIs:
|
||||
|
||||
* xref:pg-server-websocket-jetty-endpoints-container[Using `JettyWebSocketServerContainer`], which is very similar to how WebSocket endpoints are configured when using the xref:pg-server-websocket-standard-endpoints[standard `jakarta.websocket` APIs], but also provides APIs to perform a direct, programmatic, WebSocket upgrade.
|
||||
* xref:pg-server-websocket-jetty-endpoints-servlet[Using `JettyWebSocketServlet`], which may configured in `web.xml`, rather than in Java code.
|
||||
|
||||
[[pg-server-websocket-jetty-endpoints-container]]
|
||||
====== Using `JettyWebSocketServerContainer`
|
||||
|
||||
To register WebSocket endpoints using the Jetty WebSocket APIs you need to access the `JettyWebSocketServerContainer` APIs.
|
||||
|
||||
The `JettyWebSocketServerContainer` instance is stored in the `ServletContext`, so it can be retrieved when the `ServletContext` is initialized, either from a `ServletContextListener` or from a `HttpServlet`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyEndpointsInitialization]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyWebSocketInitializerServlet]
|
||||
----
|
||||
|
||||
You can also use this variant to set up the `JettyWebSocketServerContainer` and configure the WebSocket endpoints in one step:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyContainerAndEndpoints]
|
||||
----
|
||||
|
||||
When the `ServletContextHandler` is started, the `Configurator` lambda (the second parameter passed to `JettyWebSocketServletContainerInitializer.configure(\...)`) is invoked and allows you to explicitly configure the WebSocket endpoints using the Jetty WebSocket APIs provided by `JettyWebSocketServerContainer`.
|
||||
|
||||
Under the hood, the call to `JettyWebSocketServerContainer.addMapping(\...)` installs the `org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter`, which is the component that intercepts HTTP requests to upgrade to WebSocket, described in xref:pg-server-websocket-standard-upgrade[this section].
|
||||
For more information about the `WebSocketUpgradeFilter` see also xref:pg-server-websocket-configure-filter[this section].
|
||||
|
||||
One last alternative to register your WebSocket endpoints is to use a programmatic WebSocket upgrade via `JettyWebSocketServerContainer.upgrade(\...)`, which allows you to use a standard `HttpServlet` subclass (rather than a `JettyWebSocketServlet` as explained in xref:pg-server-websocket-jetty-endpoints-servlet[this section]) to perform a direct WebSocket upgrade when your application logic demands so:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyContainerServletContextHandler]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyContainerUpgrade]
|
||||
----
|
||||
|
||||
When using `JettyWebSocketServerContainer.upgrade(\...)`, the `WebSocketUpgradeFilter` is not installed, since the WebSocket upgrade is performed programmatically.
|
||||
|
||||
[[pg-server-websocket-jetty-endpoints-servlet]]
|
||||
====== Using `JettyWebSocketServlet`
|
||||
|
||||
An alternative way to register WebSocket endpoints using the Jetty WebSocket APIs is to use a `JettyWebSocketServlet` subclass (or even many different `JettyWebSocketServlet` subclasses).
|
||||
|
||||
This method has the advantage that it does not install the `WebSocketUpgradeFilter` under the hood, because the WebSocket upgrade is handled directly by your `JettyWebSocketServlet` subclass.
|
||||
This may also have a performance benefit for non-WebSocket HTTP requests (as they will not pass through the `WebSocketUpgradeFilter`).
|
||||
|
||||
Your `JettyWebSocketServlet` subclass may be declared and configured either in code or in `web.xml`.
|
||||
Declaring your `JettyWebSocketServlet` subclass explicitly in code or in `web.xml` also simplifies the declaration and configuration of other web components such as other Servlets and/or Filters (for example, it is easier to configure the `CrossOriginFilter`, see also xref:pg-server-websocket-configure-filter[this section] for more information).
|
||||
|
||||
For example, your `JettyWebSocketServlet` subclass may be declared in code in this way:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyWebSocketServletMain]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=jettyWebSocketServlet]
|
||||
----
|
||||
|
||||
Note how in the call to `JettyWebSocketServletContainerInitializer.configure(\...)` the second parameter is `null`, because WebSocket endpoints are not created here, but instead by one (or more) `JettyWebSocketServlet` subclasses.
|
||||
Yet the call is necessary to create other WebSocket implementation components that are necessary also when using `JettyWebSocketServlet` subclasses.
|
||||
|
||||
An HTTP upgrade request to WebSocket that matches your `JettyWebSocketServlet` subclass path mapping (specified above via `ServletContextHandler.addServlet(\...)`) arrives at the Servlet and is inspected to verify whether it is a valid upgrade to WebSocket.
|
||||
|
||||
If the HTTP request is a valid upgrade to WebSocket, `JettyWebSocketServlet` calls `configure(JettyWebSocketServletFactory factory)` that you have overridden in your subclass, so that your application can instantiate and return the WebSocket endpoint.
|
||||
After having obtained the WebSocket endpoint, `JettyWebSocketServlet` performs the WebSocket upgrade.
|
||||
From this point on, the communication happens with the WebSocket protocol, and HTTP components such as Filters and Servlets are not relevant anymore.
|
||||
|
||||
If the HTTP request is not an upgrade to WebSocket, `JettyWebSocketServlet` delegates the processing to the superclass, `jakarta.servlet.HttpServlet`, which in turn invokes methods such as `doGet(\...)` or `doPost(\...)` depending on the HTTP method.
|
||||
If your `JettyWebSocketServlet` subclass did not override the `doXYZ(\...)` method corresponding to the HTTP request, a `405 Method Not Allowed` response is returned to the client, as per the standard `HttpServlet` class implementation.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is possible to use both `JettyWebSocketServerContainer` and `JettyWebSocketServlet`.
|
||||
|
||||
However, it is typically best to avoid mixing the use of `JettyWebSocketServerContainer` with the use of `JettyWebSocketServlet`, so that all your WebSocket endpoints are initialized by the same code in one place only.
|
||||
====
|
||||
|
||||
Using `JettyWebSocketServerContainer.addMapping(\...)` will install the `WebSocketUpgradeFilter` under the hood, which by default will intercepts all HTTP requests to upgrade to WebSocket.
|
||||
However, as explained in xref:pg-server-websocket-standard-upgrade[this section], if `WebSocketUpgradeFilter` does not find a matching WebSocket endpoint for the request URI path, then the HTTP request is passed to the Filter chain of your web application and may arrive to your `JettyWebSocketServlet` subclass, where it would be processed and possibly result in a WebSocket upgrade.
|
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-websocket-standard]]
|
||||
==== Standard APIs Implementation
|
||||
|
||||
When you write a WebSocket application using the standard `jakarta.websocket` APIs, your code typically need to depend on just the APIs to compile your application.
|
||||
However, at runtime you need to have an implementation of the standard APIs in your class-path (or module-path).
|
||||
|
||||
The standard `jakarta.websocket` APIs are provided by the following Maven artifact:
|
||||
|
||||
[source,xml,subs=normal]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>jakarta.websocket</groupId>
|
||||
<artifactId>jakarta.websocket-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
However, the artifact above lacks a proper JPMS `module-info.class` file, and therefore it is a little more difficult to use if you want to use of JPMS for your application.
|
||||
|
||||
If you want to use JPMS for your application, you can use this Maven artifact instead:
|
||||
|
||||
[source,xml,subs=normal]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-jakarta-websocket-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
This artifact is nothing more than the `jakarta.websocket:jakarta.websocket-api:2.0.0` artifact repackaged with a proper `module-info.class` file.
|
||||
|
||||
At runtime, you also need an implementation of the standard `jakarta.websocket` APIs.
|
||||
|
||||
Jetty's implementation of the standard `jakarta.websocket` APIs is provided by the following Maven artifact (and its transitive dependencies):
|
||||
|
||||
[source,xml,subs=normal]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jakarta-server</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The `jakarta.websocket-api` artifact and the `websocket-jakarta-server` artifact (and its transitive dependencies) should be present in the server class-path (or module-path), and never in the web application's `/WEB-INF/lib` directory.
|
||||
====
|
||||
|
||||
To configure correctly your WebSocket application based on the standard `jakarta.websocket` APIs, you need two steps:
|
||||
|
||||
. Make sure that Jetty xref:pg-server-websocket-standard-container[sets up] an instance of `jakarta.websocket.server.ServerContainer`.
|
||||
. xref:pg-server-websocket-standard-endpoints[Configure] the WebSocket endpoints that implement your application logic, either by annotating their classes with the standard `jakarta.websocket` annotations, or by using the `ServerContainer` APIs to register them in your code.
|
||||
|
||||
[[pg-server-websocket-standard-container]]
|
||||
===== Setting Up `ServerContainer`
|
||||
|
||||
Jetty sets up a `ServerContainer` instance using `JakartaWebSocketServletContainerInitializer`.
|
||||
|
||||
When you deploy web applications using xref:pg-server-http-handler-use-webapp-context[`WebAppContext`], then `JakartaWebSocketServletContainerInitializer` is automatically discovered and initialized by Jetty when the web application starts, so that it sets up the `ServerContainer`.
|
||||
In this way, you do not need to write any additional code:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardContainerWebAppContext]
|
||||
----
|
||||
|
||||
On the other hand, when you deploy web applications using xref:pg-server-http-handler-use-servlet-context[`ServletContextHandler`], you have to write the code to ensure that the `JakartaWebSocketServletContainerInitializer` is initialized, so that it sets up the `ServerContainer`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardContainerServletContextHandler]
|
||||
----
|
||||
|
||||
Calling `JakartaWebSocketServletContainerInitializer.configure(\...)` must be done _before_ the `ServletContextHandler` is started, and configures the `jakarta.websocket` implementation for that web application context.
|
||||
|
||||
[[pg-server-websocket-standard-endpoints]]
|
||||
===== Configuring Endpoints
|
||||
|
||||
Once you have xref:pg-server-websocket-standard-container[setup] the `ServerContainer`, you can configure your xref:pg-websocket-endpoints[WebSocket endpoints].
|
||||
|
||||
The WebSocket endpoints classes may be either annotated with the standard `jakarta.websocket` annotations, extend the `jakarta.websocket.Endpoint` abstract class, or implement the `jakarta.websocket.server.ServerApplicationConfig` interface.
|
||||
|
||||
When you deploy web applications using xref:pg-server-http-handler-use-webapp-context[`WebAppContext`], then annotated WebSocket endpoint classes are automatically discovered and registered.
|
||||
In this way, you do not need to write any additional code; you just need to ensure that your WebSocket endpoint classes are present in the web application's `/WEB-INF/classes` directory, or in a `*.jar` file in `/WEB-INF/lib`.
|
||||
|
||||
On the other hand, when you deploy web applications using xref:pg-server-http-handler-use-webapp-context[`WebAppContext`] but you need to perform more advanced configuration of the `ServerContainer` or of the WebSocket endpoints, or when you deploy web applications using xref:pg-server-http-handler-use-servlet-context[`ServletContextHandler`], you need to access the `ServerContainer` APIs.
|
||||
|
||||
The `ServerContainer` instance is stored as a `ServletContext` attribute, so it can be retrieved when the `ServletContext` is initialized, either from a `ServletContextListener` or from a `HttpServlet`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardEndpointsInitialization]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardWebSocketInitializerServlet]
|
||||
----
|
||||
|
||||
When you deploy web applications using xref:pg-server-http-handler-use-servlet-context[`ServletContextHandler`], you can also use this variant to set up the `ServerContainer` and configure the WebSocket endpoints in one step:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/websocket/WebSocketServerDocs.java[tags=standardContainerAndEndpoints]
|
||||
----
|
||||
|
||||
When the `ServletContextHandler` is started, the `Configurator` lambda (the second parameter passed to `JakartaWebSocketServletContainerInitializer.configure(\...)`) is invoked and allows you to explicitly configure the WebSocket endpoints using the standard APIs provided by `ServerContainer`.
|
||||
|
||||
[[pg-server-websocket-standard-upgrade]]
|
||||
====== Upgrade to WebSocket
|
||||
|
||||
Under the hood, `JakartaWebSocketServletContainerInitializer` installs the `org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter`, which is the component that intercepts HTTP requests to upgrade to WebSocket, and performs the upgrade from the HTTP protocol to the WebSocket protocol.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The `WebSocketUpgradeFilter` is installed under the filter name corresponding to its class name (that is, the string `"org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter"`) and with a filter mapping of `/*`.
|
||||
|
||||
Refer to the xref:pg-server-websocket-configure-filter[advanced `WebSocketUpgradeFilter` configuration section] for more information.
|
||||
====
|
||||
|
||||
With the default configuration, every HTTP request flows first through the `WebSocketUpgradeFilter`.
|
||||
|
||||
If the HTTP request is a valid upgrade to WebSocket, then `WebSocketUpgradeFilter` tries to find a matching WebSocket endpoint for the request URI path; if the match is found, `WebSocketUpgradeFilter` performs the upgrade and does not invoke any other Filter or Servlet.
|
||||
From this point on, the communication happens with the WebSocket protocol, and HTTP components such as Filters and Servlets are not relevant anymore.
|
||||
|
||||
If the HTTP request is not an upgrade to WebSocket, or `WebSocketUpgradeFilter` did not find a matching WebSocket endpoint for the request URI path, then the request is passed to the Filter chain of your web application, and eventually the request arrives to a Servlet to be processed (otherwise a `404 Not Found` response is returned to client).
|
|
@ -12,6 +12,32 @@
|
|||
//
|
||||
|
||||
[[pg-server-websocket]]
|
||||
=== WebSocket Server Libraries
|
||||
=== WebSocket Server
|
||||
|
||||
TODO
|
||||
Jetty provides two API implementations of the WebSocket protocol:
|
||||
|
||||
* An implementation for the standard `jakarta.websocket` APIs provided by link:https://jakarta.ee/specifications/websocket/2.0/[Jakarta WebSocket 2.0], described in xref:pg-server-websocket-standard[this section].
|
||||
* An implementation for Jetty-specific WebSocket APIs, described in xref:pg-server-websocket-jetty[this section].
|
||||
|
||||
Using the standard `jakarta.websocket` APIs allows your applications to depend only on standard APIs, and your applications may be deployed in any compliant WebSocket Container that supports Jakarta WebSocket 2.0.
|
||||
|
||||
The standard APIs provide few features that are not present in the Jetty WebSocket APIs:
|
||||
|
||||
* Encoders and Decoders for automatic conversion of text or binary messages to objects.
|
||||
* `Reader` and `InputStream` for simple, blocking, message streaming.
|
||||
* Simple URI template matching.
|
||||
|
||||
On the other hand, the Jetty WebSocket APIs are more efficient and offer greater and more fine-grained control, and provide features that are not present in the standard APIs:
|
||||
|
||||
* Suspend/resume to control backpressure.
|
||||
* Remote socket address (IP address and port) information.
|
||||
* WebSocket upgrade handling via Filter or Servlet.
|
||||
* Advanced URI matching with Servlet WebSocket upgrade.
|
||||
* Control of the idle timeout.
|
||||
* Configuration of the network buffer capacity.
|
||||
|
||||
If your application needs specific features that are not provided by the standard APIs, the Jetty WebSocket APIs may provide such features -- and if they do not, you may ask for these features by submitting an issue to the Jetty Project without waiting for the standard process to approve them.
|
||||
|
||||
include::server-websocket-standard.adoc[]
|
||||
include::server-websocket-jetty.adoc[]
|
||||
include::server-websocket-filter.adoc[]
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.docs.programming.server.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.DeploymentException;
|
||||
import jakarta.websocket.server.ServerContainer;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import jakarta.websocket.server.ServerEndpointConfig;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class WebSocketServerDocs
|
||||
{
|
||||
public void standardContainerWebAppContext() throws Exception
|
||||
{
|
||||
// tag::standardContainerWebAppContext[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a WebAppContext with the given context path.
|
||||
WebAppContext handler = new WebAppContext("/path/to/webapp", "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Starting the Server will start the WebAppContext.
|
||||
server.start();
|
||||
// end::standardContainerWebAppContext[]
|
||||
}
|
||||
|
||||
public void standardContainerServletContextHandler() throws Exception
|
||||
{
|
||||
// tag::standardContainerServletContextHandler[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Ensure that JavaxWebSocketServletContainerInitializer is initialized,
|
||||
// to setup the ServerContainer for this web application context.
|
||||
JakartaWebSocketServletContainerInitializer.configure(handler, null);
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::standardContainerServletContextHandler[]
|
||||
}
|
||||
|
||||
public void standardEndpointsInitialization() throws Exception
|
||||
{
|
||||
// tag::standardEndpointsInitialization[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Ensure that JavaxWebSocketServletContainerInitializer is initialized,
|
||||
// to setup the ServerContainer for this web application context.
|
||||
JakartaWebSocketServletContainerInitializer.configure(handler, null);
|
||||
|
||||
// Add a WebSocket-initializer Servlet to register WebSocket endpoints.
|
||||
handler.addServlet(MyJavaxWebSocketInitializerServlet.class, "/*");
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::standardEndpointsInitialization[]
|
||||
}
|
||||
|
||||
@SuppressWarnings("InnerClassMayBeStatic")
|
||||
// tag::standardWebSocketInitializerServlet[]
|
||||
public class MyJavaxWebSocketInitializerServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retrieve the ServerContainer from the ServletContext attributes.
|
||||
ServerContainer container = (ServerContainer)getServletContext().getAttribute(ServerContainer.class.getName());
|
||||
|
||||
// Configure the ServerContainer.
|
||||
container.setDefaultMaxTextMessageBufferSize(128 * 1024);
|
||||
|
||||
// Simple registration of your WebSocket endpoints.
|
||||
container.addEndpoint(MyJavaxWebSocketEndPoint.class);
|
||||
|
||||
// Advanced registration of your WebSocket endpoints.
|
||||
container.addEndpoint(
|
||||
ServerEndpointConfig.Builder.create(MyJavaxWebSocketEndPoint.class, "/ws")
|
||||
.subprotocols(List.of("my-ws-protocol"))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
catch (DeploymentException x)
|
||||
{
|
||||
throw new ServletException(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::standardWebSocketInitializerServlet[]
|
||||
|
||||
public void standardContainerAndEndpoints() throws Exception
|
||||
{
|
||||
// tag::standardContainerAndEndpoints[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Setup the ServerContainer and the WebSocket endpoints for this web application context.
|
||||
JakartaWebSocketServletContainerInitializer.configure(handler, (servletContext, container) ->
|
||||
{
|
||||
// Configure the ServerContainer.
|
||||
container.setDefaultMaxTextMessageBufferSize(128 * 1024);
|
||||
|
||||
// Simple registration of your WebSocket endpoints.
|
||||
container.addEndpoint(MyJavaxWebSocketEndPoint.class);
|
||||
|
||||
// Advanced registration of your WebSocket endpoints.
|
||||
container.addEndpoint(
|
||||
ServerEndpointConfig.Builder.create(MyJavaxWebSocketEndPoint.class, "/ws")
|
||||
.subprotocols(List.of("my-ws-protocol"))
|
||||
.build()
|
||||
);
|
||||
});
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::standardContainerAndEndpoints[]
|
||||
}
|
||||
|
||||
public void jettyContainerServletContextHandler() throws Exception
|
||||
{
|
||||
// tag::jettyContainerServletContextHandler[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Ensure that JettyWebSocketServletContainerInitializer is initialized,
|
||||
// to setup the JettyWebSocketServerContainer for this web application context.
|
||||
JettyWebSocketServletContainerInitializer.configure(handler, null);
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::jettyContainerServletContextHandler[]
|
||||
}
|
||||
|
||||
public void jettyEndpointsInitialization() throws Exception
|
||||
{
|
||||
// tag::jettyEndpointsInitialization[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Ensure that JettyWebSocketServletContainerInitializer is initialized,
|
||||
// to setup the JettyWebSocketServerContainer for this web application context.
|
||||
JettyWebSocketServletContainerInitializer.configure(handler, null);
|
||||
|
||||
// Add a WebSocket-initializer Servlet to register WebSocket endpoints.
|
||||
handler.addServlet(MyJettyWebSocketInitializerServlet.class, "/*");
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::jettyEndpointsInitialization[]
|
||||
}
|
||||
|
||||
@SuppressWarnings("InnerClassMayBeStatic")
|
||||
// tag::jettyWebSocketInitializerServlet[]
|
||||
public class MyJettyWebSocketInitializerServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
// Retrieve the JettyWebSocketServerContainer.
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.getContainer(getServletContext());
|
||||
|
||||
// Configure the JettyWebSocketServerContainer.
|
||||
container.setMaxTextMessageSize(128 * 1024);
|
||||
|
||||
// Simple registration of your WebSocket endpoints.
|
||||
container.addMapping("/ws/myURI", MyJettyWebSocketEndPoint.class);
|
||||
|
||||
// Advanced registration of your WebSocket endpoints.
|
||||
container.addMapping("/ws/myOtherURI", (upgradeRequest, upgradeResponse) ->
|
||||
new MyOtherJettyWebSocketEndPoint()
|
||||
);
|
||||
}
|
||||
}
|
||||
// end::jettyWebSocketInitializerServlet[]
|
||||
|
||||
public void jettyContainerAndEndpoints() throws Exception
|
||||
{
|
||||
// tag::jettyContainerAndEndpoints[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Setup the JettyWebSocketServerContainer and the WebSocket endpoints for this web application context.
|
||||
JettyWebSocketServletContainerInitializer.configure(handler, (servletContext, container) ->
|
||||
{
|
||||
// Configure the ServerContainer.
|
||||
container.setMaxTextMessageSize(128 * 1024);
|
||||
|
||||
// Add your WebSocket endpoint(s) to the JettyWebSocketServerContainer.
|
||||
container.addMapping("/ws/myURI", MyJettyWebSocketEndPoint.class);
|
||||
|
||||
// Use JettyWebSocketCreator to have more control on the WebSocket endpoint creation.
|
||||
container.addMapping("/ws/myOtherURI", (upgradeRequest, upgradeResponse) ->
|
||||
{
|
||||
// Possibly inspect the upgrade request and modify the upgrade response.
|
||||
upgradeResponse.setAcceptedSubProtocol("my-ws-protocol");
|
||||
|
||||
// Create the new WebSocket endpoint.
|
||||
return new MyOtherJettyWebSocketEndPoint();
|
||||
});
|
||||
});
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::jettyContainerAndEndpoints[]
|
||||
}
|
||||
|
||||
@SuppressWarnings("InnerClassMayBeStatic")
|
||||
// tag::jettyContainerUpgrade[]
|
||||
public class ProgrammaticWebSocketUpgradeServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
if (requiresWebSocketUpgrade(request))
|
||||
{
|
||||
// Retrieve the JettyWebSocketServerContainer.
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.getContainer(getServletContext());
|
||||
|
||||
// Use a JettyWebSocketCreator to inspect the upgrade request,
|
||||
// possibly modify the upgrade response, and create the WebSocket endpoint.
|
||||
JettyWebSocketCreator creator = (upgradeRequest, upgradeResponse) -> new MyJettyWebSocketEndPoint();
|
||||
|
||||
// Perform the direct WebSocket upgrade.
|
||||
container.upgrade(creator, request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal handling of the HTTP request/response.
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::jettyContainerUpgrade[]
|
||||
|
||||
private boolean requiresWebSocketUpgrade(HttpServletRequest request)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void jettyWebSocketServletMain() throws Exception
|
||||
{
|
||||
// tag::jettyWebSocketServletMain[]
|
||||
// Create a Server with a ServerConnector listening on port 8080.
|
||||
Server server = new Server(8080);
|
||||
|
||||
// Create a ServletContextHandler with the given context path.
|
||||
ServletContextHandler handler = new ServletContextHandler(server, "/ctx");
|
||||
server.setHandler(handler);
|
||||
|
||||
// Setup the JettyWebSocketServerContainer to initialize WebSocket components.
|
||||
JettyWebSocketServletContainerInitializer.configure(handler, null);
|
||||
|
||||
// Add your WebSocketServlet subclass to the ServletContextHandler.
|
||||
handler.addServlet(MyJettyWebSocketServlet.class, "/ws/*");
|
||||
|
||||
// Starting the Server will start the ServletContextHandler.
|
||||
server.start();
|
||||
// end::jettyWebSocketServletMain[]
|
||||
}
|
||||
|
||||
@SuppressWarnings("InnerClassMayBeStatic")
|
||||
// tag::jettyWebSocketServlet[]
|
||||
public class MyJettyWebSocketServlet extends JettyWebSocketServlet
|
||||
{
|
||||
@Override
|
||||
protected void configure(JettyWebSocketServletFactory factory)
|
||||
{
|
||||
// At most 1 MiB text messages.
|
||||
factory.setMaxTextMessageSize(1048576);
|
||||
|
||||
// Add the WebSocket endpoint.
|
||||
factory.addMapping("/ws/someURI", (upgradeRequest, upgradeResponse) ->
|
||||
{
|
||||
// Possibly inspect the upgrade request and modify the upgrade response.
|
||||
|
||||
// Create the new WebSocket endpoint.
|
||||
return new MyJettyWebSocketEndPoint();
|
||||
});
|
||||
}
|
||||
}
|
||||
// end::jettyWebSocketServlet[]
|
||||
|
||||
@ServerEndpoint("/ws")
|
||||
private static class MyJavaxWebSocketEndPoint
|
||||
{
|
||||
}
|
||||
|
||||
@WebSocket
|
||||
private static class MyJettyWebSocketEndPoint
|
||||
{
|
||||
}
|
||||
|
||||
@WebSocket
|
||||
private static class MyOtherJettyWebSocketEndPoint
|
||||
{
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.eclipse.jetty.http.pathmap.RegexPathSpec;
|
|||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.websocket.core.Configuration;
|
||||
|
@ -223,17 +224,15 @@ public class WebSocketMappings implements Dumpable, LifeCycle.Listener
|
|||
|
||||
public boolean upgrade(HttpServletRequest request, HttpServletResponse response, Configuration.Customizer defaultCustomizer) throws IOException
|
||||
{
|
||||
// Since this may be a filter, we need to be smart about determining the target path.
|
||||
// We should rely on the Container for stripping path parameters and its ilk before
|
||||
// attempting to match a specific mapped websocket creator.
|
||||
String target = request.getServletPath();
|
||||
if (request.getPathInfo() != null)
|
||||
target = target + request.getPathInfo();
|
||||
// Since this may come from a filter, we need to be smart about determining the target path.
|
||||
// We should rely on the Servlet API for stripping URI path
|
||||
// parameters before attempting to match a specific mapping.
|
||||
String target = URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
|
||||
|
||||
WebSocketNegotiator negotiator = getMatchedNegotiator(target, pathSpec ->
|
||||
{
|
||||
// Store PathSpec resource mapping as request attribute, for WebSocketCreator
|
||||
// implementors to use later if they wish
|
||||
// Store PathSpec resource mapping as request attribute,
|
||||
// for WebSocketCreator implementors to use later if they wish.
|
||||
request.setAttribute(PathSpec.class.getName(), pathSpec);
|
||||
});
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
|
|||
}
|
||||
|
||||
private final Configuration.ConfigurationCustomizer defaultCustomizer = new Configuration.ConfigurationCustomizer();
|
||||
private WebSocketMappings mapping;
|
||||
private WebSocketMappings mappings;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||
|
@ -151,7 +151,7 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
|
|||
HttpServletRequest httpreq = (HttpServletRequest)request;
|
||||
HttpServletResponse httpresp = (HttpServletResponse)response;
|
||||
|
||||
if (mapping.upgrade(httpreq, httpresp, defaultCustomizer))
|
||||
if (mappings.upgrade(httpreq, httpresp, defaultCustomizer))
|
||||
return;
|
||||
|
||||
// If we reach this point, it means we had an incoming request to upgrade
|
||||
|
@ -173,13 +173,13 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
|
|||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
Dumpable.dumpObjects(out, indent, this, mapping);
|
||||
Dumpable.dumpObjects(out, indent, this, mappings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException
|
||||
{
|
||||
mapping = WebSocketMappings.ensureMappings(config.getServletContext());
|
||||
mappings = WebSocketMappings.ensureMappings(config.getServletContext());
|
||||
|
||||
String max = config.getInitParameter("idleTimeout");
|
||||
if (max == null)
|
||||
|
|
Loading…
Reference in New Issue