Htaccess Regex won't match - regex

I'm in desperate need of a quick tip.
Trying to use htaccess to change this not so lovely url
http://localhost/test/index.php?page=Article&articleID=61
to
http://localhost/test/article/2015-09-21-this-is-the-headline
From what I've gathered I need to send the last part to a php script which can then get the matching id from the database. Knowing that I should be able to send the user to the original url up top.
RewriteRule ^(.*)\/article\/(.*)$ redirect/article.php [L]
# RewriteRule ^(.*)$ index.php
As of right now I'm not passing the information to the script yet. redirect/article.php only contains a print statement to let me know once I get that far.
However, despite my brain and every regex debugger saying otherwise, it won't match the url provided in the second code box. All I'm getting is the good old 404. If I activate the second rule it is applied to my url, telling me that the first one is simply being skipped.
What am I missing?
.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# rename individual pages
RewriteRule ^(.*)\/article\/(.*)$ redirect/article.php [L]
# RewriteRule ^(.*)$ index.php
# resize images
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.)*\/([0-9]+)\-(([0-9]|[a-z])+)\.(prev)$ filePreview.php?id=$2&size=$3 [L]
php_value upload_max_filesize 20M
php_value post_max_size 21M
</IfModule>

The location of a .htaccess file informs how you must list paths for mod_rewrite. Inside .htaccess, paths for RewriteRule are not received with a leading /. Since yours was residing in /test, the (.*) at the start of your rule wasn't matching anything and harmless. Since that was followed by /, the article/ path was expecting a / it would never receive. The simplest fix is to change this rule to match article at the start via:
RewriteRule ^article/(.*) redirect/article.php [L]
Assuming you'll use that as a lookup in the PHP script, add a parameter to use the $1 captured pattern like:
RewriteRule ^article/(.*) redirect/article.php?article=$1 [L]

Related

htaccess not behaving like expected

I'm creating an htaccess with which I want to achieve 3 things:
remove trailing slash
redirect all requests that aren't css, ico, jpg, js, php or png files to index.php
redirect all files to view.php if the query string doesn't begin with a
At the moment it looks like this
RewriteEngine On
RewriteBase /test/
RewriteRule ^(.*)/$ $1 [N] # remove trailing slash
RewriteCond %{REQUEST_URI} !\.(css|ico|jpg|js|php|png)$ # if it isn't one of the files
RewriteRule . "index.php" [L] # then redirect to index
RewriteCond %{QUERY_STRING} !^a($|&) # if query doesn't start with a
RewriteRule . "view.php" [L] # then redirect to view
This way, the following test cases should be true:
http://127.0.0.1/test/contact -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact/ -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a
When I try these out on this site, it shows me exactly these results.In practice, however, when I'm trying out URLs, It completely breaks:
http://127.0.0.1/test/contact -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact/ -> Error 500
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a
It seems as if the script always looks at the query-related part first, although with that in mind, it still doesn't make much sense to me that /contact/ breaks. When I remove the query-related part though, the rest does work.
Did I forget about something? Is there a rule concerning the order of operation that I'm not aware of? Did I make a typo?
All input is appreciated!
P.S. I know that I will have to add a query that starts with an a for all local images, stylesheets, scripts and AJAX-calls. I'm doing this so that when people view media in a separate tab, I can create a fancy page around it, allowing people to navigate through all the media that is publicly present on the server.
Issues with your code:
First all non-css/js/image requests are routed to index.php and then anything without ?a is routed to view.php so eventually index.php won't be used at all. You need to use a negated condition in last rule for anything that doesn't have .php extension..
mod_rewrite syntax doesn't allow inline comments.
You need R flag in first rule to change URL in browser.
You can use this code in /test/.htaccess:
RewriteEngine On
RewriteBase /test/
# if not a directory then remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,NE,R=301]
RewriteCond %{REQUEST_URI} !\.(css|ico|jpe?g|js|php|png)$
RewriteRule . index.php [L]
RewriteCond %{QUERY_STRING} !(^|&)a [NC]
RewriteRule !\.php$ view.php [L,NC]

Unable to validate htaccess regex

I'm trying to redirect URLs with .htaccess in order to be able to make this:
request: http://www.example.org/business/businesswhatever/
redirect: http://www.example.org/businessgrowing/businesswhatever/
The more close I am of reaching the solution is to apply this code:
RewriteRule ^(.*)example\.org/businessgrow/(.*)$ $example.org/businessgrowing/$2 [R=301,L]
but it does not work at all. Validator doesn't check a thing, the only way to validate is if I omit http:// part of the URL.
I need to use hostname as part of the regex because some changes were made and now businessgrow is inside this path: www.example.org/corp/businessgrow, so I need to take part of the hostname in the regex in order to distingish between example.org/businessgrow (it must be a 404) and example.org/corp/businessgrow (200 OK)
I'm using this checker http://htaccess.madewithlove.be/ in order to test before deploying the solution. I tried to remove a slash from http:// (because I was unable to think anything else, I already tried anything) and it worked, but validator (I mean, it doesn't skip validation) outputs 3 slashes like this http:///www.example.org/en/businessgrow/businesswhatever/
If I input the URL without http:// code above works perfectly, but Apache doesn't recognise it and website is unable to show a single page.
I'm using Debian wheezy server and I'm using Wordpress, i took care of write this line just below REwriteBase line, so my .htacces is like this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)example\.org/businessgrow/(.*)$ $1example.org/businessgrowing/$2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I would appreciate if anybody gives me a clue in order to solve this, I think there's some mistake with validation process but I can't find it.
Thanks so much for your time!
btw, sorry about my english..
You don't want the hostname as part of the regex, only the request URI path is used to match. Try:
RewriteCond %{HTTP_HOST} example\.org$ [NC]
RewriteRule ^businessgrow/(.*)$ /businessgrowing/$1 [R=301,L]

mod_rewrite: Redirect all urls ending with "/video/[anyfilename].mp4"

Sorry for this probably very noob-style question, but I just can't get it to work.
Here's my current .htacces file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteRule ^_res/.*$ - [L] # all URLs beginning with "_res" are not changed.
# put new fancy rule doing what I want here...
RewriteRule . index.php [L] # all other URLs are redirected to index.php
</IfModule>
This works fine. It's redirecting all urls except the ones starting with "_res/" to index.php.
What I need now is that all URLs matching "[anypath]/video/[anyfilename].mp4" will be rewritten to "content/[anypath]/video/[anyfilename].mp4" (which is the actual path of this file on the server - I can't use x-sendfile on this shared web space, thus I need to rewrite large file urls to their actual server locations to avoid php's fileread-function).
From my understanding of these RewriteRules, I think I have to place this rule just before the last one.
Unfortunately my regexp-expertise is practically non-existent.
What I thought should work is this:
RewriteRule ^(.*)/video/(^/*)\.mp4$ content/$1/video/$2.mp4 [L]
The regexp should mean "starts with any amount of any characters, followed by "/video/", followed by any amount of any characters which are not '/' and ends with ".mp4".
When I insert this into my .htaccess right before the last rule, urls ending with "/video/myvid.mp4" are still rewritten to index.php.
You see me clueless. Any suggestions?
Thanks alot in advance!
I think you want:
RewriteCond %{REQUEST_URI} !^/content/
RewriteRule ^(.*)/video/([^/]+)\.mp4$ content/$1/video/$2.mp4 [L]
And you want to add this rule above the one that routes to index.php

How to do a 301 redirect in htaccess while keeping the slug of the original page

We're migrating our blog to Wordpress and need to set up 301's for all the pre-existing URL's.
The existing structure from root is as follows:
/blog/bid/148509/The-Role-of-a-Father
What we need to have it do is go to
/the-role-of-a-father (from root) on our new Wordpress blog.
Some of the problems I'm having are the following:
I do not know how to do a RewriteRule that keeps the original ending slug the same.
The numbers after /bid/ are never consistant, and so I need something that ignores those numbers but does not ignore the title slug afterwards.
I need the final URL to convert to lowercase.
I know this is quite a lot to ask for. Any help and resources would be very helpful!
Through a lot of research looking into the syntax, regex, and variable info I was able to figure out how to do this.
To help others who also might be new to .htacces, rewrites, and/or regex, I'm posted my solution, as well as what I learned.
The final product that solved my problem:
RewriteRule ^blog/bid/[0-9].*/(.*)$ /$2? [R=301,L,NC]
The full .htaccess looks like this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteRule ^blog/bid/[0-9].*/(.*)$ /$1? [R=301,L,NC]
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Basically what I did was use some regex magic on the pattern. Since the numbers after /bid/ always changed, using regex I can say "match this pattern no matter what numbers are in it" This is done using [0-9].*
[0-9] matches any character that is numbered 0-9. . matches any single character and * matches 0 or more instances of that character.
The next part is where the magic happens. The slug (permalink) after that is matched by .* and when wrapped in () is saved as a variable.
I can then use that variable in the substitution portion of my rewrite. The $1 is the variable that represents the (.*) in the pattern section. If you had more sections wrapped in () then you could use $1, $2, and so on to used saved variables from the initial pattern.
Once that was done I set my flags: R=301 sets the header redirect telling search engines that the content has moved permanently. L is the last rule that is applied when that pattern is matched (ie. don't keep trying to match rewrites). NC specifies that capitalization doesn't matter.
Note
Pay special attention to the spacing of your rules. Not having enough or having too many could cause your entire website to go down. It's especially important to know that in the flags section, there are no spaces between the commas. That bit me.
When migrating a blog, you need to use a 301 redirect.
301 redirects, by definition, will change the path in the url bar.
From memory, you'll need to do all of these steps if you need to make it lowercase too.
In your VirtualHost, add RewriteMap lc int:tolower
In your .htaccess, add:
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]
RewriteRule /blog/bid/([0-9]+)/(.*) /$2 [R=301,l]

Redirect to dynamic relative paths with .htaccess?

Is it possible to make .htaccess "understand" dynamic relative paths and redirect to them properly?
My setup goes as follows:
http://domain.com/htroot/aaa/xyz
http://domain.com/htroot/bbb/xyz
http://domain.com/htroot/ccc/xyz
And so on. For the sake of the example, "htroot" contains the .htaccess I need to modify. The following sublevels (aaa, bbb, ccc) can be any a-z0-9 name, and the folders have an index.php (or any other .php to be redirected to). The xyz should work as a parameter of sorts, see next part. The xyz part is nowhere on the filesystem as a "physical" folder or file.
What I need to achieve is the following: When you access with the url
http://domain.com/htroot/aaa/xyz
it gets content from
http://domain.com/htroot/aaa/ (or http://domain.com/htroot/aaa/index.php, either way)
where the index.php kicks in -> I can get the xyz parsed from REQUEST_URI and process it to serve the correct content that it specifies, while the URL of the page stays as http://domain.com/htroot/aaa/xyz, naturally.
So far I have managed to pull this off if every sublevel (aaa etc.) has it's own .htaccess, but I would need one where there is only a single .htaccess located in htroot that handles this. I'm guessing it might have something to do with the $0 parameters in .htaccess, but not sure.
You may want to perform something like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ /htroot/$1/index.php?data=$2 [L]
If the first wildcard match (.*) is aaa and the second wildcard match (.*) is xyz (htroot/aaa/xyz) it will get the content from
htroot/aaa/index.php?data=xyz
and you will be able to get the value xyz in index.php with $_GET['data']
OK, there's something I don't understand in the way it works, I guess I still have a lot to learn about mod_rewrite.
But like this in htroot/.htaccess file, it works:
RewriteEngine On
RewriteRule ^aaa/(.*)$ aaa/index.php?$1 [L,QSA]
RewriteRule ^bbb/(.*)$ bbb/index.php?$1 [L,QSA]
RewriteRule ^ccc/(.*)$ ccc/index.php?$1 [L,QSA]
You will be able to access $_GET['xyz'] or whatever you put after / in your index.php scripts. You will also get a bonus 'index_php' entry in the $_GET array, but I guess it's the way the internal redirect works.
This should work as a generic ruleset:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.php
RewriteRule ^(.*)/(.*) /htroot/$1/index.php?parameters=$2 [L,QSA]