rewrite image paths based on filename - apache

Right now, Im rewriting the images paths so "images/tnAhF38eS.jpg" is located at "images/tn/tnAhF38eS.jpg" with:
RewriteRule ^/images/(t([a-zA-Z0-9]).+\.jpg)$ /images/t${lc:$2|$2}/$1 [L]
First char is always "t" and second is lowercase letter or number.
But, I want to add another level based on the uppercase 3rd character so that "images/tnAhF38eS.jpg" is located at "images/tn/A/tnAhF38eS.jpg"
How do I add that?
Thanks!!

You can use the same trick that you already did with the first path. I am assuming that ${lc:$2|$2} is a RewriteMap and that you want to do that on the second path name too. I am assuming you are in VirtualHost context too (ala your current rule does something).
RewriteRule ^/images/(t([a-zA-Z0-9])([a-zA-Z0-9])[a-zA-Z0-9]+\.jpg)$ /images/t${lc:$2|$2}/${lc:$3|$3}/$1 [L]

Related

Need .htaccess recipe to display rss feed dynamically

I currently use the following recipe to route .rss files to a script that produces a rss feed dynamically:
RewriteRule ^(.*).rss$ /get-feed.pl?item=$1
It works perfectly for URLs like this:
www.example.com/articles.rss
What I would to like to do is change the URL to this:
www.example.com/rss/articles/
Everything I have tried doesn't work.
I just tried to put some slashes in the recipe but I'm not an expert in these recipes so they didn't work. Somethig like this didn't work: RewriteRule ^/rss/(.*)/$ /get-feed.pl?item=$1
("recipe" = regular expression / "regex" for short OR RewriteRule "pattern" from the Apache docs - At least I think that is what you are referring to? We are not baking a cake here! ;) )
That is very close, except that the URL-path that the RewriteRule pattern matches against does not start with a slash when used in a .htaccess (directory) context. So, it would need to be like this: ^rss/(.*)/$. If you had looked to see what your first rule was returning you would have seen that there was no slash prefix in the backreference that was captured (ie. the value of the item URL parameter).
However, there are other (minor) issues here...
The 2nd path segment cannot be empty, so it would be preferable to match something, rather than anything. eg. (.+) instead of (.*). However, this should be made more restrictive, so to match just a single path segement, instead of any URL-path (which is likely to fail anyway I suspect). eg. Presumably /rss/foo/bar/baz/ should not match?
Again, if you only want to match a string of the form articles then make the regex more restrictive so that it only matches letters (or perhaps letters + numbers + hyphens)?
You are missing the L (last) flag on this rule, which is a problem if you have other directives that follow.
So, if you are wanting to rewrite URLs of the form www.example.com/rss/articles/ (note the trailing slash) then try the following instead:
RewriteRule ^rss/([\w-]+)/$ /get-feed.pl?item=$1 [L]
Make sure the browser cache is cleared before testing.
And this would need to go near the top of the .htaccess file, before any existing rewrites.
Aside: A quick look at your original directive:
RewriteRule ^(.*).rss$ /get-feed.pl?item=$1
This is not strictly correct, as it potentially matches too much. The unescaped dot before rss matches any character. And the .* subpattern matches 0 or more characters of anything - it must be something. So, this should really be something like:
RewriteRule ^([\w-]+)\.rss$ /get-feed.pl?item=$1 [L]

question regarding specific mod_rewrite syntax

I know there are other questions that are similar to this.. but I'm really struggling with mod_rewrite syntax so I could use some help.
Basically, what I am trying to do is have the following redirect occur:
domain.com/1/ redirect to domain.com/?id=$1 (also should work for www.domain.com)
What I have so far (that isn't working):
RewriteEngine On
ReRewriteRule ^/([0-9])$ /?id=$1
A few issues.
First is terminology: if you want when a user types domain.com/1/ that the request is served by index.php?id=1, then you are rewriting /1/ to index.php?id=1, not the other way around as you said.
Second, simple typo: RewriteRule, not ReRewriteRule.
Second, [0-9] is the right way to match a number, but it'll only match a single digit. If you want to handle /13 then you should match one or more instances [0-9] by writing [0-9]+.
Third, the target of your rule should be the file you want to serve. / is not a file or an absolute URL, write out the index.php if that's what you mean.
Third, you say you want to handle /1/, but your rule says that the matched request must end in a number, not a slash. If you want to accept the slash whether it's there or not, put that in the rule.
RewriteRule ^/?([0-9]+)/?$ index.php?id=$1 [L]
Does that work?
You've three issues:
RewriteRule is misspelt as point out by Michael, you need to worry about the trailing slash, and you need to stop processing rules when you've found the match:
RewriteRule ^/(\d+)/?$ /?id=$1 [L]
You have misspelled RewriteRule. Otherwise, I think your syntax looks correct.
RewriteEngine On
ReRewriteRule ^/([A-Za-z0-9]+)$ /?id=$1
--^^^---------
Actually, you should probably remove the /:
RewriteEngine On
RewriteRule ^([A-Za-z0-9$_.+!*'(),-]+)$ /?id=$1
------^^^---------
EDIT Added the +. Look at all the answers here. You need a composite of them., including the + and the [L] in addition to what I have here.
EDIT2 Also edited to include alpha characters in the id.
EDIT3 Added special characters to regex. These should be valid in a URL, but it's unusual to find them there.

mod rewrite help

I am trying to use mod rewrite to remove and replace part of my url. I am looking to get my urls looking like this.
http://domain.com/e813c697e8dd8dc2bbfecb1d20b15783.html
instead of
http://domain.com/lookup.php?md5=e813c697e8dd8dc2bbfecb1d20b15783
lookup.php calls matches the md5 to the database and fetches and forwards you to the correct url.
All I need to do now is rewrite it so that it rewrites from this
http://domain.com/lookup.php?md5=e813c697e8dd8dc2bbfecb1d20b15783
to this
http://domain.com/e813c697e8dd8dc2bbfecb1d20b15783.html
I have tried this which works but it makes rewrites from any .html page at root level and makes it display nothing "blank".
RewriteRule ^([a-z0-9]+)\.html$ /lookup.php?md5=$1
Can anyone tell me a way to do this so that my regular html pages are not messed up and be able to display these links how I want to? Thanks.
Your current rule is a way too broad. You need to make it more specific to only match md5 hash value -- which is easy:
RewriteRule ^([a-f0-9]{32})\.html$ /lookup.php?md5=$1 [QSA,L]
Your pattern for file name is too broad -- it will match any file with letters and digits. md5 hash, on another hand, uses very limited subset of characters (a-f only) and digits .. and has to be 32 characters long. This pattern ([a-f0-9]{32}) does the job perfectly.
I have also added L and QSA flags (QSA to preserve any existing query string (like, tracking info, for example) and L to stop matching any other rules).
To further ensure that it does not match any real files which may have name in such format (who knows), add RewriteCond %{REQUEST_FILENAME} !-f line before the rule.
One thing you can do is quantify the number of hex digits:
RewriteRule ^([0-9a-f]{32})\.html$ /lookup.php?md5=$1
as md5 will always have 32 hex digits.
That depends on the naming scheme of your regular html pages. For starters though you could change it to: RewriteRule ^([a-f0-9]+)\.html$ /lookup.php?md5=$1
Which would make any html pages which have a letter not between a and f work.
If none of your HTML pages have numbers in their names, and if the cost of a page not redirecting outweighs the odds of an md5 hash having no numbers in it. You could check that there is at least one digit in the filename: RewriteRule ^([a-f]*\d[a-f\d]+)\.html$ /lookup.php?md5=$1
Lastely if it is acceptable for you to have urls like http://domain.com/md5/e813c697e8dd8dc2bbfecb1d20b15783.html instead you could change it to: RewriteRule ^md5/([a-f0-9]+)\.html$ /lookup.php?md5=$1 and not have to worry about the fragileness of the other methods.
I'm not sure, but I think you have a RewriteBase / somewhere in you .htaccess judging by your example mod_rewrite. If not you might need to add a / right after the ^ in whatever RewriteRule you choose to go with.

mod_rewrite: do not apply here

I am using mod_rewrite to put a category name in the URL, like locahost/categoryName and also a location localhost/categoryName/locationName .
One question I had, and I'm sure it's easy to do as a rewrite rule, is how can I make it so that the rule does not apply to some specific directory, like: localhost/admin . In that case I want it to go to the actual physical directory.
Thanks
Make this your first rule:
RewriteRule localhost/admin - [L]
That means: match localhost/admin, do nothing, last rule (only if matched).

Mod Rewrite problem

I have a problem that I cannot wrap my head around.
I'm using Apache and PHP
I need to get:
http://localhost.com/cat_ap.php?nid=5964
from
http://localhost.com/cat_ap~nid~5964.htm
How do I go about changing that around? I have done more simple mod rewrites but this is slightly more complicated. Can anyone give me a leg up or point me in the right direction
RewriteRule ^/cat_ap~nid~(.*)\.htm$ /cat_ap?nid=$1 [R]
The [R] at the end is optional. If you omit it, Apache won't redirect your users (it will still serve the correct page).
If the nid part is also a variable, you can try this:
RewriteRule ^/cat_ap~([^~]+)~(.*)\.htm$ /cat_ap?$1=$2 [R]
EDIT: As Ben Blank said in his comment, you might want to restrict the set of valid URLs. For example, you might want to make sure a nid exists, and that it's numerical:
RewriteRule ^/cat_ap~nid~([0-9]+)\.htm$ /cat_ap?nid=$1
or if the nid part is a variable, that it only consists of alphabetical characters:
RewriteRule ^/cat_ap~([A-Za-z]+)~([0-9]+)\.htm$ /cat_ap?$1=$2
Assuming the variable parts here are the "nid" and the 5964, you can do:
RewriteRule ^/cat_ap~(.+)~(.+).htm$ ^/cat_ap?$1=$2
The first "(.+)" matches "nid" and the second matches "5964".
If you want everything arbitrary:
RewriteRule ^/(\w+)~(\w+)~(\w+)\.htm$ $1?$2=$3 [L]
Where \w is equal to [A-Za-z0-9_]. And if you want to use this rule in a .htaccess file, remove the leading / from the pattern.