During the Resource Resolution step, the client request URI (as being returned by HttpServletRequest.getRequestURI()) is decomposed into the following parts (in exactly this order):
.
) or it is the full request URI. Otherwise (for a path not matching any existing resource) the resource path ends at the first dot (.
) in the request url. The exact logic for retrieving the resource path is implemented at ResourceResolver.resolve(HttpServletRequest, String) called from org.apache.sling.engine.impl.request.RequestData.initResource()
with the 2nd argument being the request path. It is impossible to tell from just looking at the request URI where the resource path part ends. You have to know the underlying resource structure to know how a URL is decomposed. You cannot safely assume that the resource path will always end at the first dot!..
), the string after the dot up to but not including the last dot before the next slash character or the end of the request URL comprises the selectors. If the resource path spans the complete request URL no selectors exist. If only one dot follows the resource path before the end of the request URL or the next slash, also no selectors exist.In addition since SLING-848 there may be one or multiple request path parameters passed in the form ;<key>=<value>
. Those request path parameters are only supported directly after the Resource Path or after the Extension. The value needs to be enclosed in '
if it contains a .
and is not located after the extension. It is up to the Resource Provider to decide for what purpose those parameters are being used and which ones are supported at all.
The decomposed parts can be accessed through the RequestPathInfo
object, which is retrieved via SlingHttpServletRequest.getPathInfo().
There's a cheat sheet in Adobe's AEM documentation at https://experienceleague.adobe.com/docs/experience-manager-cloud-service/implementing/developing/full-stack/sling-cheatsheet.html available to get you familiar with the URL decomposition of Sling.
Assume there is a Resource at /a/b
, which has no children.
URI | Resource Path | Selectors | Extension | Suffix | Resource Found |
---|---|---|---|---|---|
/a/b | /a/b | null | null | null | yes |
/a/b.html | /a/b | null | html | null | yes |
/a/b.s1.html | /a/b | s1 | html | null | yes |
/a/b.s1.s2.html | /a/b | s1.s2 | html | null | yes |
/a/b/c/d | /a/b/c/d | null | null | null | no! |
/a/c.html/s.txt | /a/c | null | html | /s.txt | no! |
/a/b./c/d | /a/b | null | null | /c/d | yes |
/a/b.html/c/d | /a/b | null | html | /c/d | yes |
/a/b.s1.html/c/d | /a/b | s1 | html | /c/d | yes |
/a/b.s1.s2.html/c/d | /a/b | s1.s2 | html | /c/d | yes |
/a/b/c/d.s.txt | /a/b/c/d | s | txt | null | no! |
/a/b.html/c/d.s.txt | /a/b | null | html | /c/d.s.txt | yes |
/a/b.s1.html/c/d.s.txt | /a/b | s1 | html | /c/d.s.txt | yes |
/a/b.s1.s2.html/c/d.s.txt | /a/b | s1.s2 | html | /c/d.s.txt | yes |
/a/b.s1;v='1.0'.html/c/d | /a/b | s1 | html | /c/d | yes, in case Resource Provider supports request path parameter v with value 1.0 |
/a/b.html;v=1.0/c/d | /a/b | null | html | /c/d | yes, in case Resource Provider supports request path parameter v with value 1.0 |
The tests at
testBasicAPIAssumptions
.Feel free to suggest additional tests that help clarify how this works!