Enhance urlrewrite.xml to add querystring when trailing slash is missing

I just added the following enhancement request to Jira: [PRESIDECMS-2800] - JIRA

That’s an interesting problem. When adding an URL Redirect and calling it without the trailing slash, tuckey rewrite is automatically adding the trailing slash, but not the query string.

In our use case the url redirect was used for some FB campaign and the fbclid parameter was added. The trailing slash was not added by the customer. But due to the “wrong” urlrewrite rule, the query sting wasn’t added.

The solution was pretty simple: Tuckey rewrite has an option for adding the querystring automatically. I changed the trailing slash rule to the following and this solved the issue:

      <name>Add trailing slash to directories without a trailing slash</name>
      <to type="permanent-redirect" last="true" qsappend="true">$1/</to>

notice the qsappend="true" attribute.

Don’t know if there are some more rules that makes sense, so I wrote it in the category collaboration.


Ah, interesting. Works in my local environment, but not as expected on my production system. Here a missing trailing slash results in the following URL: https://www.my.domain/myURLRedirect/&abe=123/

It still forwards to the correct target, but not with the added params.

Did you enter a ? in the original URL? Has it changed the ? to &?

Or did you enter & in the original URL, which is why it’s redirecting there?

my original redirect URL was: https://my.domain/myRedirect?param=value

This redirects to https://my.domain/redirectTarget. Without the param.

I did an additional logging in the website user actions with an interceptor:

public void function onPresideUrlRedirects( event, interceptData ) {

And my Logging is:

	public void function logEntryForRedirect( required string path, required string fullUrl, required string loggedInUser ) {
		var ruleDao = _getRuleDao();
		var dbAdapter = ruleDao.getDbAdapter();
		var match = _getRuleDao().selectData(
			  selectFields = ["id", "redirect_type", "redirect_to_link", "keep_query_string" ]
			, filter       = "( exact_match_only = '1' and source_url_pattern = :source_url_pattern ) or ( exact_match_only = '0' and :source_url_pattern like #dbAdapter.getConcatenationSql( 'source_url_pattern', "'%'" )# )"
			, filterParams = { source_url_pattern = arguments.path }
			, orderBy      = "#dbAdapter.getLengthFunctionSql( 'source_url_pattern' )# desc"
			, maxRows      = "1"

		if(!isEmpty(match)) {

      var recordAction = {};
      recordAction.identifier = match.id;
			recordAction.action = "redirect";
			recordAction.type = "urlredirect";
      recordAction.userId = arguments.loggedInUser;
      recordAction.detail = { fullUrl : arguments.fullUrl };

      var logged = _getwebsiteUserActionService().recordAction( argumentCollection = recordAction );

In psys_website_user_action (production) I have a detail value of: {"fullUrl":"https://my.domain/myRedirect/&dwdww2/"}

But: Having the same on my local environment (commandbox) my psys_website_user_action entry has: {"fullUrl":""}

That’s really interesting. I have no idea, what is different here. Is tuckey different? Is Preside doing something different? I’d bet on tuckey or tomcat behaviour.

Curious, isn’t it?

BTW: The customer request was: Please do some redirect loggin in Preside so we now where the link is coming from and what the UTM Params are.