.htaccess rewrite rule - custom structure - .htaccess

Is it possible to create a .htaccess rule which will take the middle of a URL structure, but resume the normal REQUEST_URL (Sorry for my terrible explanation)
Take this URL for example
/boats/283/manage/water
Now let's say I'm keeping the hierarchy standardisation as per the URL structure, minus the ID (ID in this case is 287) - so the actual script location is /boats/manage/water(.php)
But obviously I don't have to have a manual rule for each page, as that will get tedious.
eg (What I want to avoid per page).
RewriteRule ^boats/(\d+)/manage/water$ ./boats/manage/water.php?id=$1
RewriteRule ^boats/(\d+)/manage/bacon$ ./boats/manage/bacon.php?id=$1
I have no doubt I could find something relevant in Google, but I just can't quite come up with the proper keywords..
Any help/push in the right direction is much appreciated :)

You can try:
# group out the first path, the ID, then the rest
RewriteCond %{REQUEST_URI} ^/([^/]+)/(\d+)/(.*)$
# pre-check that the destination php file actually exists
RewriteCond %{DOCUMENT_ROOT}/%1/%3.php -f
# rewrite
RewriteRule ^ /%1/%3.php?id=%2 [L]

Related

htaccess redirect url if matching exact string length?

I have a lot of old urls inbound pointing to incorrect locations, trying to forward to new location. These are going to the root directory so I can't just forward everything.
One way to get a good chunk of them on to the new place is finding ones with a session ID in the query string. It always has 32 characters, preceded by s=
https://www.example.com/some-url-name-1233/?s=ba4a8a734b666b8d43499e5d497599a6
Need to move that to (and drop the session ID)
https://www.example.com/newfolder/some-url-name-1233/
I can't get the .htaccess redirect to match that string.
I've tried multiple ways, most recent being:
RewriteRule ^(.*)s=([^.]{32})$ https://www.example.com/newfolder/$1 [L,R=301]
Any suggestions?
This is an often answere, fully documented issue: you cannot access a request's query string by means of a RewriteRule. You need to use a RewriteCond for that:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^s=[^&]{32}(&|$)
RewriteRule ^ https://www.example.com/newfolder%{REQUEST_URI} [L,R=301,QSD]
I also fixed some other details.

URL redirect to use subdirectory as GET parameter

I imagine this has to be a common scenario but I'm struggling to describe it sufficiently well or to find a working answer!
Essentially I want to make hundreds of URLS that include unique reference codes but that are easy to type in the form example.com/aabbcc, which will be intercepted and all delivered to a PHP script for validating that code, located somewhere like example.com/script.php.
I need the subdirectory part of the URL (aabbcc, in this example) to become a GET parameter for that script, so a URL like the one above would be sent to example.com/script.php?id=aabbcc, while hiding this more complicated URL from the user.
I can see from other .htaccess examples that this must be possible, but I can't find one doing this.
Is there a .htaccess solution for it? Is there something else even more basic? Your help is appreciated in steering me.
If your "unique reference codes" consist of 6 lowercase letters, as in your example then you can do something like the following in your root .htaccess file using mod_rewrite:
RewriteEngine
# Internally rewrite "/abcdef" to "script.php?id=abcdef"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^[a-z]{6}$ script.php?id=$0 [L]
If you don't need direct access to any subdirectories off the root that also happen to match a "unique reference code" then you can remove the preceding condition (RewriteCond directive). With the condition in place then you naturally can't access any "unique access codes" that happen to also match the name of a subdirectory.
$0 is a backreference to the entire URL-path that the RewriteRule pattern (first argument) matches against.
Reference
Apache mod-rewrite Documentation - Contents
Apache mod_rewrite Introduction
Apache mod_rewrite Reference
RewriteRule Directive
RewriteCond Directive

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

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