URL Rewriting and extra parameters

34 views
Skip to first unread message

Doug

unread,
Jul 7, 2009, 2:44:33 PM7/7/09
to Mach-II for CFML
Hello List,

I'm working through the configuration of SES URLs in Mach-II 1.8,
having made some progress but still missing something along the way.
Module/event routing is currently working correctly, but extra
parameters beyond the event that are delimited with slashes are
ignored.

Here are my URL related Mach-II configuration properties:

<!-- Enable URL re-writing with BuildURL -->
<property name="urlParseSES" value="true" />
<!-- Use slashes for all delimiters -->
<property name="urlDelimiters" value="/|/|/" />
<property name="moduleDelimiter" value="/" />
<!-- Remove index.cfm from the URL -->
<property name="urlBase" value="" />
<!-- Don't show the event parameter -->
<property name="urlExcludeEventParameter" value="true" />

And here are my Apache rewrite rules:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)/([A-Za-z0-9-_\.]+)/(.*)" "/index.cfm?
event=$1/$2/$3" [NC,QSA]

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)/([A-Za-z0-9-_\.]+)" "/index.cfm?event=
$1/$2" [NC,QSA]

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)/?$" "/index.cfm?event=$1/" [NC,QSA]

These configurations allow me to do this:

http://example.com/<module>/<event>

And, that works great. However, any parameters that follow the event
are ignored, apparently by the way that
RequestManager.parseSesParameters() works.

For example, the dashboard works fine if I call it with this URL:

http://example.com/dashboard/info.index/

Except that none of the image/css/js files are loaded because the path
to them is not being parsed correctly. For example, this url:

http://local.www.daveramsey.com/dashboard/sys.serveAsset/path/%40js%40generic.js

includes the "path" parameter needed by the dashboard's sys.serveAsset
event, but parseSesParameters() is looking for that in the
cgi.PATH_INFO. However, PATH_INFO is empty, as everything is being
sent to the QUERY_STRING by my mod_rewrite rule.

I've tried many different permutations of different rewrite rules and
Mach-II URL configs in an attempt to pass the whole URL in the
PATH_INFO instead of the QUERY_STRING. No matter what I've tried I
have been unable to make the URL example shown here work:

http://greatbiztoolsllc.trac.cvsdude.com/mach-ii/wiki/URLManagementFeatures#HowToDoSearchEngineSafeFriendlyURLs

The example there is: "/index.cfm/event/displayMusician/firstName/Bob/
lastName/Dylan/".

All attempts to pass a URL like that to ColdFusion (without a real ?
to delimit the query string) completely fail.

Bottom line after this long message -- I need to be able to append
arbitrary parameters in the URL as shown above. What am I missing?

Thanks!

Doug
http://www.daveramsey.com


Matthew

unread,
Jul 8, 2009, 6:47:24 PM7/8/09
to Mach-II for CFML
Hi Doug

I don't have time to read your full post however a quick comment
regarding the re write rules. I've found in the past that anything
after the "?" character doesn't re write. I use ISAPI ReWrite in IIS
so not sure if it has the same problems Apache. Just a thought because
I ran into this problem as well. Just do a simple test to test me
issue.

Cheers
MAtthew
> http://local.www.daveramsey.com/dashboard/sys.serveAsset/path/%40js%4...
>
> includes the "path" parameter needed by the dashboard's sys.serveAsset
> event, but parseSesParameters() is looking for that in the
> cgi.PATH_INFO. However, PATH_INFO is empty, as everything is being
> sent to the QUERY_STRING by my mod_rewrite rule.
>
> I've tried many different permutations of different rewrite rules and
> Mach-II URL configs in an attempt to pass the whole URL in the
> PATH_INFO instead of the QUERY_STRING. No matter what I've tried I
> have been unable to make the URL example shown here work:
>
> http://greatbiztoolsllc.trac.cvsdude.com/mach-ii/wiki/URLManagementFe...

Doug

unread,
Jul 9, 2009, 9:55:53 AM7/9/09
to Mach-II for CFML
Hi Matthew,

Thank you for your response. My message was long and involved, but the
problem is complex and difficult to describe. I'm not trying to
rewrite anything after a ? in the input URL; instead, I'm trying to
figure out how to make Mach-II's SES features work as the
documentation describes.

To restate, I'm trying to make an input URL that comes in to Apache
like this:

(a.) http://example.com/moduleName/eventName/paramName/paramValue/param2Name/param2Value/

To be rewritten like this for ColdFusion/Mach-II:

(b.) http://example.com/index.cfm/moduleName/eventName/paramName/paramValue/param2Name/param2Value/

Right now, my rewrite rule takes the input one above and turns it into
a URL like this:

(c.) http://example.com/index.cfm?event=moduleName/eventName/paramName/paramValue/param2Name/param2Value/

Which passes to the right module and event, but the params after the
eventName are ignored.

The docs seem to show that (b.) should work, but I can't see how for
the reasons shown in my earlier message. I'm looking forward to
hearing more as this is a blocker for my current project.

Thanks!

Doug

Peter J. Farrell

unread,
Jul 9, 2009, 7:45:56 PM7/9/09
to mach-ii-for...@googlegroups.com
Doug,

Are you just trying to get the index.cfm out the URL? You cannot set the
module delimiter to "/" so this won't work well:

/index.cfm?event=$1/$2" [NC,QSA]

Leave it at the standard ":" for now or change it to a "." or "-"
(provided that none of your event handler names uses that delimiter.
The module delimiter must be unique.

The parseSESUrl means that Mach-II is going to look for data in the
cgi.path_info for you (basically it's a simplistic mod_rewrite without
the URL rewriting functions). If you are going to let your web server
do that, then set that parameter to false.

Any SES URLS that are being rewritten, you'll need to use the HTML <base
href=""> tag directive to tell the browser where to look for assets.

Doug said the following on 07/07/2009 01:44 PM:


> Except that none of the image/css/js files are loaded because the path
> to them is not being parsed correctly. For example, this url:
>
> http://local.www.daveramsey.com/dashboard/sys.serveAsset/path/%40js%40generic.js
>

This is because the dashboard uses an event-handler to serve all images
and css/js. Somewhere your rewrite rules aren't working.


> includes the "path" parameter needed by the dashboard's sys.serveAsset
> event, but parseSesParameters() is looking for that in the
> cgi.PATH_INFO. However, PATH_INFO is empty, as everything is being
> sent to the QUERY_STRING by my mod_rewrite rule.
>

I'd just consider letting Mach-II do everything if you are just trying
to remove the index.cfm by using a rule like this:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d

RewriteRule "^/(.*)?$" "/index.cfm/$1" [NC,QSA]

By just adding in the index.cfm file to the URL and letting Mach-II
parse the path_info data for you. You'll have to make sure you're not
rewriting URLs to CSS / JS / image / docs directory in your rules.


> I've tried many different permutations of different rewrite rules and
> Mach-II URL configs in an attempt to pass the whole URL in the
> PATH_INFO instead of the QUERY_STRING. No matter what I've tried I
> have been unable to make the URL example shown here work:
>
> http://greatbiztoolsllc.trac.cvsdude.com/mach-ii/wiki/URLManagementFeatures#HowToDoSearchEngineSafeFriendlyURLs
>
> The example there is: "/index.cfm/event/displayMusician/firstName/Bob/
> lastName/Dylan/".
>
> All attempts to pass a URL like that to ColdFusion (without a real ?
> to delimit the query string) completely fail.
>

If you are using Tomcat (and possibly other application servers), you
loose the cgi.path_info -- there are ways to get it in there, but I
don't know your server tier setup.

.Peter

Doug

unread,
Jul 10, 2009, 11:02:33 AM7/10/09
to Mach-II for CFML
Hi Peter, thank you for your response. Please see below:

On Jul 9, 6:45 pm, "Peter J. Farrell" <pe...@mach-ii.com> wrote:

> Leave it at the standard ":" for now or change it to a "." or "-"
> (provided that none of your event handler names uses that delimiter.
> The module delimiter must be unique.

Using a module delimiter of "/" is actually working well for us.
BuildURL is writing the correct URLs, and our rewrite rules *do*
correctly put the index.cfm back into the URL and pass the module and
event to ColdFusion. That works fine.

What we're missing are any additional parameters that follow the
module/event, like:

/module/event/param1/val1/param2/val2

However, we may have a rewrite rule strategy that even passes those
along correctly, but it unfortunately bypasses parseSesParameters().

On Jul 9, 6:45 pm, "Peter J. Farrell" <pe...@mach-ii.com> wrote:
> If you are using Tomcat (and possibly other application servers), you
> loose the cgi.path_info -- there are ways to get it in there, but I
> don't know your server tier setup.

We are using Tomcat/JBoss. Is that why this fails? If you know of
workarounds so that the cgi.PATH_INFO is passed correctly in Tomcat,
that would be very helpful. I'll install JRun again locally and try it
that way in the mean time.

Thanks!

Doug

Peter J. Farrell

unread,
Jul 10, 2009, 11:40:21 AM7/10/09
to mach-ii-for...@googlegroups.com
Doug said the following on 07/10/2009 10:02 AM:
Hi Peter, thank you for your response. Please see below:

On Jul 9, 6:45 pm, "Peter J. Farrell" <pe...@mach-ii.com> wrote:

  
Leave it at the standard ":" for now or change it to a "." or "-"
(provided that none of your event handler names uses that delimiter.
The module delimiter must be unique.
    
Using a module delimiter of "/" is actually working well for us.
BuildURL is writing the correct URLs, and our rewrite rules *do*
correctly put the index.cfm back into the URL and pass the module and
event to ColdFusion. That works fine.
  
Well, you are rewriting them to query string parameters so I expect this to work -- however if you were letting Mach-II do the SES parsing -- it would fail because it's expecting the moduleName:eventName as one string.  It basically explodes the /list/of/items/ into an array and uses the name value pairs.

What we're missing are any additional parameters that follow the
module/event, like:

/module/event/param1/val1/param2/val2
  
Just so we're not missing anything, what do your rewritten URLs look like?  They need to look like this if you are not going to parse each of the additional parameters into the query string elements.

index.cfm/param1/value1/param2/value2/?event=moduleName/eventName

SES parameters (aka cgi.path_info) comes after the file name and before query string.

However, we may have a rewrite rule strategy that even passes those
along correctly, but it unfortunately bypasses parseSesParameters().
  
Well, parseSesParameters() only works if there is a data in the cgi.path_info variable.

On Jul 9, 6:45 pm, "Peter J. Farrell" <pe...@mach-ii.com> wrote:
  
If you are using Tomcat (and possibly other application servers), you
loose the cgi.path_info -- there are ways to get it in there, but I
don't know your server tier setup.
    
We are using Tomcat/JBoss. Is that why this fails? If you know of
workarounds so that the cgi.PATH_INFO is passed correctly in Tomcat,
that would be very helpful. I'll install JRun again locally and try it
that way in the mean time.
  
I assuming you are using Adobe ColdFusion.  Sadly Adobe did not ship a SES parameter servlet and Tomcat does not pass path info data to ColdFusion.  Other engines like Open BD has a SES parameter servlet that does this.

You can do a little trickery, but I'm not sure if it will universally work.  In you WEB-INF folder for your CF deployment on Tomcat, open the web.xml file.  Scroll about 7/8's of the way down and you'll see this block of code that is commented out:

    <!--
    If your J2EE server supports it, you can uncomment these.
    They are included to support Search Engine Safe (SES) URL types.
    Some servers (Tomcat, SunONE) don't support wildcard mappings
    -->
    <!-- begin SES
  <servlet-mapping id="coldfusion_mapping_6">
     <servlet-name>CfmServlet</servlet-name>
     <url-pattern>*.cfml/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping id="coldfusion_mapping_7">
    <servlet-name>CfmServlet</servlet-name>
    <url-pattern>*.cfm/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping id="coldfusion_mapping_8">
    <servlet-name>CFCServlet</servlet-name>
    <url-pattern>*.cfc/*</url-pattern>
  </servlet-mapping>
  end SES -->

The statement in the comment is partially true.  Tomcat won't work wildcard mappings for *.cfm/* (in which there is a wild card for the file name) but is works with a complete file names like index.cfm/*  So add this servlet-mapping:

  <servlet-mapping id="coldfusion_mapping_7">
    <servlet-name>CfmServlet</servlet-name>
    <url-pattern>/index.cfm/*</url-pattern>
  </servlet-mapping>

The id for the servlet-mapping needs to be unique, but coldfusion_mapping_7 should be ok if you do not uncomment any of the other mappings.  The trick is Mach-II is front-controller framework, so all calls to a index.cfm will get the path info data passed along. Oh, this only works if the path to index.cfm from the root of the domain name is /index.cfm.  If you have applications in sub-folders (like example.com/otherApp/index.cfm), you'll need to add another servlet mapping with the url pattern of /otherApp/index.cfm/*

Hope this helps.

Best,
.Peter

P.s.  If this works for you, would you consider updating / adding information (you can use the information in my email as a basis) to that wiki page?  I'd appreciate it if you could.

Peter J. Farrell

unread,
Jul 10, 2009, 11:56:09 AM7/10/09
to mach-ii-for...@googlegroups.com
Just wanted to say your rewrite rule from what I explained before should look like this:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)/([A-Za-z0-9-_\.]+)/(.*)" "/index.cfm/$3?event=$1/$2" [NC,QSA]

This is because the path info stuff must be after the file name and the query string parameters comes after that.

I'm not convinced that the module delimiter of "/" will work all the time because in the base application, the module doesn't exist in the URL.  With a module:

/index.cfm/moduleName/eventName/param1/value1/

Whereas in the base application, it looks like this:

/index.cfm/eventName/param1/value1/

You're rewrite rules will match stuff up strangely in this case because the regex will think the module name is the value in the position of "eventName" and the event name will be in the position of "param1".   This is why you'll probably have an easier time with the regex if your module delimiter is unique (using a ":" or you can use a "_" or "-" if they are not being used in event-handler names).

When a module exists using a module delimiter of ":":
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+):([A-Za-z0-9-_\.]+)/(.*)" "/index.cfm/$3?event=$1/$2" [NC,QSA]
Or with "-"
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)\-([A-Za-z0-9-_\.]+)/(.*)" "/index.cfm/$3?event=$1/$2" [NC,QSA]
Base app urls without a module would look like this:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)/(.*)" "/index.cfm/$3?event=$1/$2" [NC,QSA]
Using a unique module delimiter will also let you pass on everything as a SES param as well instead of rewriting stuff into the query string (because some request will like using PUT instead of POST for search forms).

This rule will pass query string data as well if available.  No query string:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)\-([A-Za-z0-9-_\.]+)/(.*)" "/index.cfm/$1-$2/$3/?" [NC,QSA]

With query string:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule "^/([A-Za-z0-9-_]+)\-([A-Za-z0-9-_\.]+)/(.*)\?(.*)" "/index.cfm/$1-$2/$3/?$4" [NC,QSA]
FYI, I haven't tested this rewrite strings directly -- just typing from memory -- so you'll have to check them.

.Peter

Doug said the following on 07/10/2009 10:02 AM:

Aaron West

unread,
Jul 10, 2009, 6:57:20 PM7/10/09
to mach-ii-for...@googlegroups.com
I love this topic! I got caught up in Apache rewrite and Mach-ii stuff when modules version came out in version 1.5
of Mach-ii. I wrote a blog post that explains how to create "go" URLs that filter through Apache's mod_rewrite and
pass the appropriate URL structure for Mach-ii modules. Check it out if you are interested.



-- 
| Aaron West
| http://www.trajiklyhip.com/blog
| Certified Advanced Adobe ColdFusion MX 7 Developer
| Certified Macromedia Flash MX Developer
| Adobe Community Expert

Matthew Woodward

unread,
Jul 10, 2009, 7:33:17 PM7/10/09
to mach-ii-for...@googlegroups.com
Aaron West wrote:
> I wrote a blog post that explains how to create "go" URLs
> that filter through Apache's mod_rewrite and
> pass the appropriate URL structure for Mach-ii modules. Check it out if
> you are interested.
>
> http://tinyurl.com/2mfpkv

Thanks Aaron! I missed this when you first posted it.

If you get a chance and don't mind sharing, can you copy/paste the
Mach-II-specific information up on the wiki? Or if you don't have time,
and with your permission and credit to you along with a link to your
blog post, I can post it up there.

It's great info and I'd love to have it in the wiki when people search
on this topic.


--
Matthew Woodward
ma...@mattwoodward.com
http://www.mattwoodward.com/blog

Please do not send me proprietary file formats such as Word, PowerPoint,
etc. as attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

Reply all
Reply to author
Forward
0 new messages