The Servlet API exposes the full request path as requestURI
and further splits it into
contextPath
, servletPath
and pathInfo
, the meanings of which depend on how
the servlet is rendered. From this input, Spring MVC must determine the search path that will be used to map the
handler, which is the path in the mapping of DispatcherServlet
itself, excluding
contextPath
and any servletMapping
prefix, if present.
ServletPath
and pathInfo
are decoded, making it impossible to directly compare them with
the full requestURI
to obtain the lookupPath, so decoding becomes necessary requestURI
.
However, this poses its own problems because the path may contain encoded reserved characters such as
"/"
or ";"
, which may change the structure of the path after they are decoded, which may
also lead to security problems. Additionally, servlet containers may normalize servletPath
to varying
degrees, making it even more impossible to compare startsWith
with requestURI
.
This is why it is best to avoid depending on the servletPath
that accompanies the prefix-based servletPath
mapping type. If DispatcherServlet
is rendered as a default servlet with a "/"
sign, or
otherwise rendered without a prefix with a "/*"
sign, and the servlet container is versioned 4.0+, then
Spring MVC will be able to determine the servlet's mapping type and completely avoid the use of
servletPath
and pathInfo
. In a 3.1 servlet container, assuming the same servlet mapping
types are used, a similar result can be achieved by providing UrlPathHelper
with alwaysUseFullPath=true
via Path Matching in the MVC configuration.
Fortunately, the default servlet mapping "/"
is a smart choice. However, there is still the issue that
requestURI
needs to be decoded to be able to compare with controller mappings. This is again
undesirable due to the possibility of decoding reserved characters which will change the path structure. If such
characters are not expected, you can block them (as in the Spring Security HTTP firewall), or you can configure
UrlPathHelper
with urlDecode=false
, but the controller mappings will need to match the
encoded path, which doesn't always work acceptably. Moreover, sometimes DispatcherServlet
has to share
URL space with another servlet, and this may require mapping by prefix.
The above problems can be solved more thoroughly by moving from PathMatcher
to the parsed PathPattern
,
available in version 5.3 and higher. Unlike AntPathMatcher
, which requires either a decoded search path
or an encoded controller mapping, a parsed PathPattern
is matched to a parsed path representation
called RequestPath
, by one path segment at a time. This allows path segment values to be decoded and
cleared individually without the risk of changing the path structure. A parsed PathPattern
also
supports the use of a servletPath
prefix mapping, as long as the prefix is kept simple and does not
contain characters that need to be encoded.