Parse Entire URL in ColdFusion - .htaccess

I am trying to figure out how to parse an entire URL in ColdFusion.
By entire URL I mean something link this - http://subdomain.domainname.com/crm/leads/view/
I can figure out the first part by using the CGI.HTTP_HOST which gives me - subdomain.domainname.com. I cannot figure out how to read the - crm/leads/view/ part of the URL.
Is there a variable I can use to read that? I found some UDFs that will parse a full string like that for me but I need to be able to pass it the full URL.
I am also using URL Rewriting so that complicates it some. The URL could be http://subdomain.domainname.com/crm/leads/view/ but the actual page that is serving is http://subdomain.domainname.com/public/index.cfm.
I know this is the way many Frameworks work where all URLs are routed to a file and then it some how parses the URL and directs it to a certain controller and action.
Here is a copy of my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.cfm [NC,L]
Any feedback on this would be great.
Thanks!

Ok, I'm going to make a few assumptions based on the SES URLs above, what you're trying to do, and how to work it into CGI.PATH_INFO below.
Root directory, .htaccess file:
RewriteEngine On
RewriteCond %{THE_REQUEST} /crm/([^?\ ]+)
RewriteRule ^.*$ /public/index.cfm/%1 [NC,L]
/public directory. .htaccess file:
RewriteEngine Off
This will redirect into CGI.PATH_INFO, for parsing. Read on for how to parse that.
When you are using Search-Engine Safe (SES) URLs, where your keys/values are all delimited by forward slashes, ColdFusion will consider these in the CGI.PATH_INFO server variable, usually reserved for directories.
So, knowing that, use a simple extraction mechanism to parse it:
<cfset SESQueryString = CGI.PATH_INFO />
<cfset num_pairs = ListLen(SESQueryString,'/') />
<cfset keyVals = StructNew() />
<cfloop from="1" to="#num_pairs#" step="2" index="i">
<cfset keyVals[ListGetAt(SESQueryString,i,'/')] = ListGetAt(SESQueryString,i+1,'/') />
</cfloop>
<cfdump var=#keyVals#>
Keep in mind that this answer assumes you have an even number of key/val matches in CGI.PATH_INFO. Also remember that List* functions in CF will (in many cases) will throw away an empty list value, so you may think you have an even number, you actually do not.
Scan the list functions on Adobe LiveDocs or cfquickdocs.com to see if the list function you are working with has a parameter you can pass it that will cause it to force empty list values in your list to not be tossed away. One such function is ListToArray().

Related

mod_rewrite .htaccess with %20 translate to -

I have been reading about .htaccess files for a couple of hours now and I think I'm starting to get the idea but I still need some help. I found various answers around SO but still unsure how to do this.
As far as I understand you write a rule for each page extension you want to 'prettify', so if you have something.php , anotherpage.php, thispage.php etc and they are expecting(will receive??) arguments, each needs its own rule. Is this correct?
The site I want to change has urls like this,
maindomain.com/sue.php?r=word1%20word2
and at least one page with two arguments
maindomain.com/kevin.php?r=place%20name&c=person%20name
So what I would like to make is
maindomain.com/sue/word1-word2/
maindomain.com/kevin/place-name/person-name/
Keeping this .php page and making it look like the directory. Most of the tutorials I have read deal with how to remove the .php page to which the argument is passed. But I want to keep it.
the problem I am forseeing is that all of the .php?r=parts of the url are the same ie sue.php?r=, kevin.php?r= and the .htaccess decides which URL to change based on the filename and then omits it. If I want to keep the file name will I have to change the ?r=
so that it is individual? I hope this make sense. So far I have this, but I'm sure it won't work.
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)/$1.php?r=$1
RewriteRule ^([a-zA-Z0-9]+)/$1.php?r=$1&c=$1
And I think I have to add ([^-]*) this in some part or some way so that it detects the %20 part of the URL, but then how do I convert it to -. Also, how are my $_GET functions going to work??
I hope my question makes sense
You're missing a space somewhere in those rules, but I think you've got the right idea in making 2 separate rules. The harder problem is converting all the - to spaces. Let's start with the conversion to GET variables:
# check that the "sue.php" actually exists:
RewriteCond %{REQUEST_URI} ^/([a-zA-Z0-9]+)/([^/]+)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/?$ /$1.php?r=$2 [L,QSA]
RewriteCond %{REQUEST_URI} ^/([a-zA-Z0-9]+)/([^/]+)/([^/]+)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/?$ /$1.php?r=$2&c=$3 [L,QSA]
Those will take a URI that looks like /sue/blah/ and:
Extract the sue part
Check that /document_root/sue.php actually exists
rewrite /sue/blah/ to /sue.php?r=blah
Same thing applies to 2 word URI's
Something like /kevin/foo/bar/:
Extract the kevin part
Check that /document_root/kevin.php actually exists
3 rewrite /kevin/foo/bar/ to /kevin.php?r=foo&c=bar
Now, to get rid of the "-" and change them to spaces:
RewriteCond %{QUERY_STRING} ^(.*)(c|r)=([^&]+)-(.*)$
RewriteRule ^(.*)$ /$1?%1%2=%3\ %4 [L]
This looks a little messy but the condition matches the query string, looks for a c= or r= in the query string, matches against a - in the value of a c= or r=, then rewrites the query string to replace the - with a (note that the space gets encoded as a %20). This will remove all the - instances in the values of the GET parameters c and r and replace them with a space.

CFM redirect 301

On Google I have a site that has a bunch of old links to its pages, they are links like this.
/mainpage.cfm?linkId=84&LinkType=mainlink
I want to 301 redirect them with htaccess, but nothing I am trying works.
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/architectural
RewriteRule .* /mainpage.cfm?linkId=84&LinkType=mainlink
Any Ideas, I have tried many varients of this, it seems the problem is the .cfm file.
Your question is a bit fuzzy. You say you want to rewrite from /mainpage.cfm?linkId=84&LinkType=mainlink, but then you also have that as the target of your RewriteRule. So I think some wires are crossed somewhere. Can you please update your question to include "I want to rewrite [this current URL example] to [the URL you wish the first one to end up at]". Also any other considerations that might require a RewriteCond, and any variations in the patterns.
Then we can get your rules/conditions sorted out.
To answer your exact question as asked, your RewriteCond will reject /mainpage.cfm?linkId=84&LinkType=mainlink because that does not match ^/architectural.
However I suspect this is not the question you mean to ask...
in mod_rewrite RewriteRule can only see the directory and file part of the URI and not the query string. So to match the query string you need to use RewriteCond.
e.g.
RewriteCond %{QUERY_STRING} linkId=(\d+)&LinkType=mainlink [NC]
RewiteRule ^mainpage\.cfm newpage.php?linkid=%1 [NC,L]
I have matched the linkId in the RewriteCond which I then refer to by %1 in the RewriteRule as this is the syntax for matching groups in a RewriteCond.
As #AdamCameron points out you don't state where you want to redirect to, but this should give you the tools to resove it.
You could perform the redirect within the ColdFusion page instead. Just add the following line to the top of the mainpage.cfm file (assuming you want every request of that page redirected). You could add some condition logic if you only want to redirect specific linkId and/or LinkType based on the URL parameter.
Again, if you want every request to the mainpage.cfm to redirect just add this to the top of that file (NOTE you need to change the url for the redirected page):
<cflocation url="http://host/architetural" statusCode="301" addtoken="no">
The statusCode attribute was added in ColdFusion 8 - so you must be running that or newer

Revising my ReWrite Code

Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*)\.html$ fetch.php?id=$1
I have this in my htaccess file and it works fine, but I want to know if there is a way to rewrite this so that instead of just pulling the id # i can pull the category and title up instead or will i need to do something like this
RewriteRule (.*)/(.*)/(.*)\.html$ fetch.php?id=$1&category=$2&title=$3
Also if this is what I need to do, how will I go about changing my title to have no spaces and only have dashes inbetween them? I heard that urls don't like spaces. I have read somewhere else they used a php code where the spaces were turned into "-" or "_" to be read into the page but reverted back to be read in sql. Let me know if you need to know more about my situation. Thanks.
UPDATE!
RewriteRule (.*)/(.*)/(.*)\.html$ fetch.php?id=$1&category=$2&title=$3
This is the htaccess rule
<a href="<?php echo $row_getDisplay['id']; ?>/<?php echo $row_getDisplay['category']; ?>/<?php echo urlencode($row_getDisplay['title']); ?>">
that is my link .. this method I get it to pull up with id/category/title with no spaces but it has no css or images displaying. i'm pulling by ID because that's how my fetch.php is pulling it i don't know how to set it so it pulls by category and title.
this method I get it to pull up with id/category/title with no spaces but it has no css or images displaying. i'm pulling by ID because that's how my fetch.php is pulling it i don't know how to set it so it pulls by category and title.
This is probably because all your links are relative, and the base URI has changed from /something.html (i.e. /) to /something/foo/bar.html (i.e. /something/foo/) so all the relative links are now broken. Try adding this to the header of your pages:
<base href="/">
I would advise against doing this as this is not very extensible, you might want to try the following:
Add the following in your htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* fetch.php/%{REQUEST_URI} [QSA,L]
This will put your entire url into the path_info environment variable, which you can than use in your backend code.
The RewriteCond parts make sure the url only gets rewritten if the file requested doen't actually exist.

.htaccess issue with redirecting folder

I have a folder named /test in my application.
Right now i am trying to write an .htaccess file that would show all requests to /test* as /test.
For example:
www.example.com/test/ is the actual directory with index.php file in it.
All the requests like the following should go to the same /test directory
www.example.com/test-hello/
www.example.com/test-world/
www.example.com/test-htacess/
www.example.com/test123/
Basically any requests to /test* should go to /test.
This is what I've tried so far:
RewriteRule ^/test* /test
You need to use RewriteCond to first match "test in url"
Try below:
RewriteCond %{THE_REQUEST} ^GET\ /test/
RewriteRule ^test/(.*) /test/$1 [L,R=301]
Your regular expression is wrong. You mean ^/test.*$. Your rule would match to /testtttt.
The asterisk means that the char in front of it can be zero or more times included. The dot is a special char which means here could be anything. the .* matches every string including an empty string. See also Wikipedia.
You currently are not putting the -hello, -world etc behind your folder. What is hello? Is that the file? Or the param?
The second part of the rewriteRule should be a file. Something like
RewriteRule ^/test(.*)$ /test/$1.php
Above function will have:
/testABC to /test/ABC.php
But I don't understand what you want to accomplish?

URL Beautification using .htaccess

in search of a more userfriendly URL, how do i achieve both of the following, elegantly using only .htaccess?
/de/somepage
going to /somepage?ln=de
/zh-CN/somepage#7
going to /somepage?ln=zh-CN#7
summary:
/[language]/[pagefilenameWithoutExtension][optional anchor#][a number from 0-9]
should load (without changing url)
/[pagefilenameWithoutExtension]?ln=[language][optional anchor#][a number from 0-9]
UPDATE, after provided solution:
1. exception /zh-CN/somepage should be reachable as /cn/somepage
2. php generated thumbnails now dont load anymore like:
img src="imgcpu?src=someimage.jpg&w=25&h=25&c=f&f=bw"
RewriteRule ^([a-z][a-z](-[A-Z][A-Z])?)/(.*) /$3?ln=$1 [L]
You don't need to do anything for fragments (eg: #7). They aren't sent to the server. They're handled entirely by the browser.
Update:
If you really want to treat zh-CN as a special case, you could do something like:
RewriteRule ^zh-CN/(.*) /$1?ln=zh-CN [L]
RewriteRule ^cn/(.*) /$1?ln=zh-CN [L]
RewriteRule ^([a-z][a-z])/(.*) /$2?ln=$1 [L]
I would suggest the following -
RewriteEngine on
RewriteRule ^([a-z][a-z])/([a-zA-Z]+) /$2?ln=$1
RewriteRule ^([a-z][a-z])/([a-zA-Z]+#([0-9])+) /$2?ln=$1$3
The first rule takes care of URLs like /de/somepage. The language should be of exactly two characters
length and must contain only a to z characters.
The second rule takes care of URLs like /uk/somepage#7.

Resources