Rewrite anything except existing files - regex

I basically want to rewrite any request starting with foo/ to foo/index.php?url=. For example, http://localhost/foo/something should become http://localhost/foo/index.php?url=something.
I currently have this rule:
RewriteRule ^foo/(\w*) foo/index.php?url=$1
This works on my localhost, but not on a free hosting service online. The point is, that it there also rewrites existing files... So my layout has gone, as well as all images etc, because foo/style.css becomes foo/index.php?url=style.css. This isn't happening on my localhost.
I came across this similar question: mod_rewrite: Redirect if anything but a file, but it didn't do anything actually.
So how would I go about rewriting anything except existing files here? Why does it only work on my own localhost?

If this does not work:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^foo/(\w*) foo/index.php?url=$1
try this:
RewriteRule ^foo/(\w*)$ foo/index.php?url=$1
with added $ sign. But this doesn't rewrite URLs with non-word chars like a dot (so foo/style.css wont be rewritten).

Maybe if you add the extension to the regex? That is to say requestion the dot not to be present?
RewriteRule ^foo/[^.]+ foo/index.php?url=$1
Or I guess you can add the $ to your own
RewriteRule ^foo/(\w*)$ foo/index.php?url=$1
Cause else it can match files since foo/style matches (you did not require next char to be end of URL)
How is it?

Related

Rewrite rule with pagination .htaccess

I have a URL like this:
http://example.com/category/title which comes from the link http://example.com/cview.php?url=title
I want to create pagination and to be like http://example.com/category/title/page/1 or
http://example.com/category/title/1
this comes from http://example.com/cview.php?url=title&pageno=1.
I have tried this in .htaccess without success
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^/]*)$/([^/]+)/?$ /cview.php?url=$2&pageno=$1 [L]
Can anyone help please?
RewriteRule ^category/([^/]*)$/([^/]+)/?$ /cview.php?url=$2&pageno=$1 [L]
You have an erroneous $ (end-of-string anchor) in the middle of the RewriteRule pattern. You also appear to have the backreferences $1 and $2 the wrong way round. You are also allowing an optional trailing slash, yet your example URLs do not use this. (An optional trailing slash potentially creates a duplicate content issue.)
If you allow both /category/title/page/1 and /category/title/1 then you are potentially creating a duplicate content issue. Presumably you are only linking to one of these URL formats?
Since the page number is a "number" then it makes sense to just match numbers, rather than anything - this also helps to avoid conflicts with other directives.
It doesn't look like you need the conditions (RewriteCond directives) that check the request does not map to a file or directory, since I wouldn't expect a request of the form /category/title/page/1 to map to a file or directory anyway?
Try the following instead (without the RewriteCond directives):
RewriteRule ^category/([^/]+)(?:/page)?/(\d+)$ /cview.php?url=$1&pageno=$2 [L]
This matches both /category/title/page/<num> and /category/title/<num>. The optional subpattern (?:/page) is non-capturing, so that it doesn't mess up the numbering of the backreferences.
Bear in mind also that the order of the rules in .htaccess is important in order to avoid conflicts.

Ommitting a specific folder in htaccess redirect

Im trying to redirect a bunch of support files to a different support system except for any files that have the folder software_updates in them. the following is the rule that I wrote.
RewriteRule ^/support/.*(?!software_updates).*$ newurl_location [NC,L,R=301]
this excludes /support/software_updates/ but not /support/product/software_updates Im trying to exclude any URL that has software_updates anywhere in the URL after support.
Try:
RewriteRule ^/support/(?!.*software_updates) newurl_location [NC,L,R=301]
I don't have Apache handy to test it, but it should work.
I have tested this and believe that it is what you're looking for (please note the changes in the / and the .* )
RewriteRule ^support/(?!.*?software_updates) newurl_location [NC,L,R=301]
You were nearly there.
First off, you don't need the initial /
You don't want .*(?!software_updates).*, because this will match software_updates. Why? The dot-star eats the whole string, then, at the end, you have the assertion that software_updates is not next. And of course this is true.
This should do the trick.
RewriteRule ^support/(?!.*software_updates).*$ newurl_location [NC,L,R=301]

My apache rewrite only works for the first folder level

We have a website where we show clients creative work we have produced for them. We upload raw assets to a path like this:
x.com/clients/clientName/campaignName/size/
I have a PHP script which adds our branding, contact information and other information and pulls in the raw creative (usually a swf object). It is in this directory x.com/clients/index.php and it accepts a query string parameter ?path so it knows where to look for the creative.
I am trying to do an apache rewrite in .htaccess so that our designers can upload directly to the known folder structure but so that when you go to x.com/clients/clientName/campaignName/size/ it should rewrite to x.com/clients/index.php?path=clientName/campaignName/size/
I am currently using the following rewrite rule, which works for the first folder level e.g. x.com/clients/clientName/ does successfully rewrite, but any subsequent folders do not.
RewriteRule ^clients/([^/\.]+)/?$ /clients/index.php?path=$1 [L]
My RegEx's are terrible, so I'm stuck on what to do. Any help appreciated, thank you kindly.
Your regex is only matching urls like clients/xxxxxx/ because your pattern [^/\.]+ means one or many characters except "/" or "."
With your rule, it can't work for other subdirectories.
You can change your rule by this one
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
To avoid internal server error (code 500 which means an infinite loop in this case), you can do it this way
RewriteRule ^clients/index\.php$ - [L]
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
Is there a special reason you want to use regex? In my opinion you can just catch everything coming after /clients:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(.*/)?index\.php$ [NC]
RewriteRule ^clients/(.*)$ /clients/index.php?path=$1 [L]
The second line is to prevents redirect loops, because the index.php is also in the folder /clients and this would cause never ending redirects.

How do I use .htaccess rewrite to a cache subdirectory using the first letter of the request?

I have a caching program that creates static html files of dynamically generated php files. I currently use php to check if the cached version exists, if it does I serve it up and php exits. As in this question (http://stackoverflow.com/questions/5612735/using-mod-rewrite-to-view-cached-version-from-usual-url), I feel this is a waste of time. However, I have around 5,000 pages and as such, I would prefer not to place them all in the same /cache/ directory. I would instead like to place
/a-web-url/ in /cache/a/a-web-url.html.gz
and
/this-is-another-url/ in /cache/t/this-is-another-url.html.gz
I am currently working with
RewriteRule ^([A-Za-z0-9-_/\.]+)/$ /cache/$1
However this assumes that all are in the same directory. I would prefer them to be divided into subdirectories. Thanks.
Also note that all of my files end in .html.gz
Use rule
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/?cache/ [NC]
RewriteRule ^/?(.)(.*?)/?$ /cache/${lc:$1}/${lc:$1}${lc:$2}.html.gz [L]
Something like this should work:
RewriteRule ^([a-z])([A-Za-z0-9-_/\.]+)/$ /cache/$1/$1$2
You are matching more than one upper case, lower case, dashes and underscores with your current pattern. You can modify this to match just the first character using the same character class, and then the rest using the + modifier, and rewrite using the $1 back reference for the first character and $2 for the rest. Using (!?cache/) will prevent it from matching URLs that begin with /cache/.
RewriteRule ^(!?cache/)([A-Za-z0-9-_/\.])([A-Za-z0-9-_/\.]+)/$ /cache/$1/$1$2 [L]
You can test this rule here: http://htaccess.madewithlove.be/
If you want to make the first character lower case you can add RewriteMap tolower int:tolower to your <VirtualHost> config and then use ${tolower:$1} for the first character.

mod_rewrite performing unexpectedly

I can't figure this one out no matter how many times I google it or think about it. I have a RewriteRule in my .htaccess file: RewriteRule ^/download/([^/\.])/?$ /downloadfile.php?f=$1 [L]
When I use this, my page loads fine, but going to the link http://www.example.com/download/file.ext, it pulls a 404 page. However, if I load the page, then change my RewriteRule to RewriteRule ^/download/([^/\])/?$ /downloadfile.php?f=$1 [L] (noting the RegEx change), the link works exactly how I expect it to... Until I reload the page, which results in a 500 error because of a bad regex expression? (I checked my Apache error log, thats how I know it reads as a bad regex)
So, what can I do to make this work? I've tried (.*) and ([.*]) for regex as well, that didn't work either.. can anyone tell me what I'm doing wrong?
mod_rewrite strips out the prefix (the leading slash) from the URI when you use it in an .htaccess file. Your regex needs to have it removed:
RewriteRule ^download/([^/\.]*)/?$ /downloadfile.php?f=$1 [L]
This should work:
RewriteRule ^/?download/([^/]*) /downloadfile.php?f=$1 [L]
The leading slash is required in apache 1.x and stripped in version 2.x
You were also denying the dot character.