[[filters]]
= Filters

[.small]#xref:web/webflux/reactive-spring.adoc#webflux-filters[See equivalent in the Reactive stack]#

The `spring-web` module provides some useful filters:

* xref:web/webmvc/filters.adoc#filters-http-put[Form Data]
* xref:web/webmvc/filters.adoc#filters-forwarded-headers[Forwarded Headers]
* xref:web/webmvc/filters.adoc#filters-shallow-etag[Shallow ETag]
* xref:web/webmvc/filters.adoc#filters-cors[CORS]
* xref:web/webmvc/filters.adoc#filters.url-handler[URL Handler]

Servlet filters can be configured in the `web.xml` configuration file or using Servlet annotations.
If you are using Spring Boot, you can
{spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare them as beans and configure them as part of your application].


[[filters-http-put]]
== Form Data

Browsers can submit form data only through HTTP GET or HTTP POST but non-browser clients can also
use HTTP PUT, PATCH, and DELETE. The Servlet API requires `ServletRequest.getParameter{asterisk}()`
methods to support form field access only for HTTP POST.

The `spring-web` module provides `FormContentFilter` to intercept HTTP PUT, PATCH, and DELETE
requests with a content type of `application/x-www-form-urlencoded`, read the form data from
the body of the request, and wrap the `ServletRequest` to make the form data
available through the `ServletRequest.getParameter{asterisk}()` family of methods.


[[filters-forwarded-headers]]
== Forwarded Headers
[.small]#xref:web/webflux/reactive-spring.adoc#webflux-forwarded-headers[See equivalent in the Reactive stack]#

include::partial$web/forwarded-headers.adoc[]

[[filters-forwarded-headers-non-forwardedheaderfilter]]
=== ForwardedHeaderFilter

`ForwardedHeaderFilter` is a Servlet filter that modifies the request in order to
a) change the host, port, and scheme based on `Forwarded` headers, and b) to remove those
headers to eliminate further impact. The filter relies on wrapping the request, and
therefore it must be ordered ahead of other filters, such as `RequestContextFilter`, that
should work with the modified and not the original request.

[[filters-forwarded-headers-security]]
=== Security Considerations

There are security considerations for forwarded headers since an application cannot know
if the headers were added by a proxy, as intended, or by a malicious client. This is why
a proxy at the boundary of trust should be configured to remove untrusted `Forwarded`
headers that come from the outside. You can also configure the `ForwardedHeaderFilter`
with `removeOnly=true`, in which case it removes but does not use the headers.

[[filters-forwarded-headers-dispatcher]]
=== Dispatcher Types

In order to support xref:web/webmvc/mvc-ann-async.adoc[asynchronous requests] and error dispatches this
filter should be mapped with `DispatcherType.ASYNC` and also `DispatcherType.ERROR`.
If using Spring Framework's `AbstractAnnotationConfigDispatcherServletInitializer`
(see xref:web/webmvc/mvc-servlet/container-config.adoc[Servlet Config]) all filters are automatically registered for all dispatch
types. However if registering the filter via `web.xml` or in Spring Boot via a
`FilterRegistrationBean` be sure to include `DispatcherType.ASYNC` and
`DispatcherType.ERROR` in addition to `DispatcherType.REQUEST`.


[[filters-shallow-etag]]
== Shallow ETag

The `ShallowEtagHeaderFilter` filter creates a "`shallow`" ETag by caching the content
written to the response and computing an MD5 hash from it. The next time a client sends,
it does the same, but it also compares the computed value against the `If-None-Match`
request header and, if the two are equal, returns a 304 (NOT_MODIFIED).

This strategy saves network bandwidth but not CPU, as the full response must be computed for each request.
State-changing HTTP methods and other HTTP conditional request headers such as `If-Match` and
`If-Unmodified-Since` are outside the scope of this filter. Other strategies at the controller level
can avoid the computation and have a broader support for HTTP conditional requests.
See xref:web/webmvc/mvc-caching.adoc[HTTP Caching].

This filter has a `writeWeakETag` parameter that configures the filter to write weak ETags
similar to the following: `W/"02a2d595e6ed9a0b24f027f2b63b134d6"` (as defined in
{rfc-site}/rfc7232#section-2.3[RFC 7232 Section 2.3]).

In order to support xref:web/webmvc/mvc-ann-async.adoc[asynchronous requests] this filter must be mapped
with `DispatcherType.ASYNC` so that the filter can delay and successfully generate an
ETag to the end of the last async dispatch. If using Spring Framework's
`AbstractAnnotationConfigDispatcherServletInitializer` (see xref:web/webmvc/mvc-servlet/container-config.adoc[Servlet Config])
all filters are automatically registered for all dispatch types. However if registering
the filter via `web.xml` or in Spring Boot via a `FilterRegistrationBean` be sure to include
`DispatcherType.ASYNC`.


[[filters-cors]]
== CORS
[.small]#xref:web/webflux/reactive-spring.adoc#webflux-filters-cors[See equivalent in the Reactive stack]#

Spring MVC provides fine-grained support for CORS configuration through annotations on
controllers. However, when used with Spring Security, we advise relying on the built-in
`CorsFilter` that must be ordered ahead of Spring Security's chain of filters.

See the sections on xref:web/webmvc-cors.adoc[CORS] and the xref:web/webmvc-cors.adoc#mvc-cors-filter[CORS Filter] for more details.


[[filters.url-handler]]
== URL Handler
[.small]#xref:web/webflux/reactive-spring.adoc#filters.url-handler[See equivalent in the Reactive stack]#

In previous Spring Framework versions, Spring MVC could be configured to ignore trailing slashes in URL paths
when mapping incoming requests on controller methods. This means that sending a "GET /home/" request would be
handled by a controller method annotated with `@GetMapping("/home")`.

This option was deprecated in 6.0 and removed in 7.0, but applications are still expected to handle such
requests in a safe way. The `UrlHandlerFilter` Servlet filter has been designed for this purpose.
It can be configured to:

* respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant.
* wrap the request to act as if the request was sent without a trailing slash and continue the processing of the request.

Here is how you can instantiate and configure a `UrlHandlerFilter` for a blog application:

include-code::./UrlHandlerFilterConfiguration[tag=config,indent=0]
