URLMap Pattern description & Fallthrough

In the documentation for URL Maps an embedded image shows something curious - it has a double slash before wikiTitle.

This seems to imply that both:

/docs/slugs-and-url-maps-seo-friendly-urls
and
/docs/latest/slugs-and-url-maps-seo-friendly-urls

would resolve, but there is NO documentation of this at all, the helper for creating an URLMap does not mention it at all! Is there some actual description of what the URLMap pattern could do?

Secondly, I put in the following in the Config Overrides in the Maintenance/System Info:

DOT_URLMAP_FALLTHROUGH false

But it doesn’t work at all. I just get ‘404’ (/inventory/kawasaki renders, but /inventory/kasasaki goes to a 404 page.)
I did restart the entire system after putting in the Config Override.

Hey Mark. Great observations, both very useful!

  1. I think the image might actually contain a typo, as I’ve never before seen the double-slash mid-pattern like that. I’ve updated it to show the current doc content type, which does not have this curiosity.
  2. I believe the URLMAP_FALLTHROUGH issue may be a full-on bug; my own testing replicates your report exactly. I’ve created a defect issue accordingly: URLMAP_FALLTHROUGH no longer functional · Issue #33062 · dotCMS/core · GitHub

Lastly, I also made a small change on the site code — which should already be visible — correcting that weird spacing issue between parent and child lists.

Before:

After:

Thanks for the feedback!

Thanks…love the name!

I have never seen that double-slash as well, but your site definitely manages to do something unusual:
/docs/slugs-and-url-maps-seo-friendly-urls AND
/docs/latest/slugs-and-url-maps-seo-friendly-urls both resolve to the same page.

I’m looking to do something flexible like:
/inventory/new/kawasaki
/inventory/kawasaki both working so the ‘new’ is optional, in the same manner that ‘latest’ appears optional. I can’t reproduce that functionality, though. It DOES accept // for the second parameter, though.

Maybe you just have the FALLTHROUGH working on your docs site, though.

Unless there was some clever way to patch over the Scripting API endpoint. (I want clean urls, not /api/vtl/inventory/new)

Okay, NOW I am being truly evil - maybe if I intercept the 404…and iterate on the javax.forward….

I think Vanity Urls can work here as a stand in for the FALLTHROUGH. Use a Vanity pattern to redirect everything under /inventory/(.*) to a detail page and then just parse the url and get the content using a content query.

Last time I tested this it worked fine.

1 Like

GREAT idea. Thanks! Plus FALLTHROUGH is per site and I really wasn’t sure it was worth doing it.

but your site definitely manages to do something unusual:
/docs/slugs-and-url-maps-seo-friendly-urls AND
/docs/latest/slugs-and-url-maps-seo-friendly-urls both resolve to the same page.

To make it a little less mysterious, this is handled by the joint workings of a redirect plus URL Map behavior. I was about to say that it involved Vanity URL, but I just checked and that’s not it.

“Oh, right,” I said, “because we used a rule.” Nope, not that, either.

In our case, as we were rebuilding the docs site to run headless, we ended up building the redirect right into our next.config.js:

{
source: ‘/docs/latest/:path’,
destination: ‘/docs/:path’,
permanent: true,
},

It can be most righteous when the cup runneth over with options, though sometimes it can also send you retracing your steps. :sweat_smile:

Here’s code that allows for bulletproof mapping. It can take new/used, kawasaki, scooter, in ANY order and works with accidental plurals.

#set ($inaddress=$request.getAttribute(“javax.servlet.forward.request_uri”))

#set ($inaddress=$inadress.toLowerCase())

#set ($terms=$inaddress.split(“/”))

#set ($brands=$dotcontent.pull(“+contentType:Brand”,0,“modDate desc”))

#set ($cats=$dotcontent.pull("+contentType:CategoryShopItem ",0,“modDate desc”))

#set ($catfound=“”)

#set ($brandfound=“”)

#set ($condfound=“”)

#foreach ($term in $terms)

#if ($term==“new”) #set ($condfound=“new”) #end

#if ($term==“used”) #set ($condfound=“used”) #end

#set ($lengther=$term.length())

#set ($lengther=$math.sub($lengther,1))

#set ($singleterm=$term.substring(0, $lengther))

$singleterm $lengther

#foreach ($brand in $brands)

#if ($brand.urlTitle==$term || $brand.urlTitle==$singleterm) #set ($brandfound=$brand) #end

#end

#foreach ($cat in $cats)

#if ($cat.urlTitle==$term || $cat.urlTitle==$singleterm) #set ($catfound=$cat) #end

#end

#end

##of term search

Cat :$catfound.title Brand:$brandfound.title Condition:$condfound

##create some html so javascript can properly read this info.