Redirect to dynamic relative paths with .htaccess? - regex

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]

Related

Using htaccess, how do you re-write for parameters over 8 characters or more only?

Using .htaccess file, I am trying to re-write the URL when the 'folder' is 8 or more characters long only. In other words:
https://example.com/blog - goes to the /blog folder
- but -
https://example.com/12345678 - goes to https://example.com/script.php?id=12345678
Ideally, the answer would ensure that https://example.com/12345678/ still works too (note the trailing slash /).
This is for a Linux server running on a shared hosting plan - think Hostgator, GoDaddy, etc.
This is so wrong, but:
RewriteRule ^(.*)$ [>8character]? "script.phpid=$1" ? "";
How about:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/script.php.*$
RewriteRule ^([^\/]{8,})[^\/]*$ "/script.php?id=$1" [R,L]
Uses RewriteCond as extra guard against a redirect loop
By default, the original query string is discarded when adding a new one, so if you want to preserve the original (so, example.com/12345678?utm_campaign=foo goes to example.com/script.php?id=12345678&utm_campaign=foo) use the [QSA] flag, like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/script.php.*$
RewriteRule ^([^\/]{8,})[^\/]*$ "/script.php?id=$1" [QSA,R,L]
If the ID is always just numbers, you could change the Regex to ^(\d{8,})[^\/]*$ to make it a little more foolproof.

.htaccess redirect with GET parameters and URL condition

I try to redirect to another domain and changing the URL structure (not keeping URI part) based on 2 conditions:
The original URL has "lang" parameter.
The original URI begins with "page".
It's Apache 2.2
This is working when only have the lang paramenter in the orginal URL:
RewriteCond %{QUERY_STRING} lang=en$
RewriteRule ^.*$ https://www.destination.com/en/? [R=301,L]
For example it redirects ok for:
http://www.origin.com/?lang=en
to:
http://www.destination.com/en/
But I also need to redirect something like:
http://www.origin.com/page/5/?lang=en
to:
http://www.destination.com/en/
I'm trying things like this, but doesn't work, I think there's something wrong in the RewriteRule pattern:
RewriteCond %{QUERY_STRING} ^lang=en$
RewriteRule ^/page/.*/?$ https://www.destination.com/en/? [R=301,L]
Welcome!
You may not want to do have a ? at the end of your RewriteRule. However, if you wish to have you can do so. Maybe, you want to have a RewriteRule similar to:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} lang=en$
RewriteRule (.*)(\?lang=en) https://www.destination.com/en/ [R=301,L]
</IfModule>
You might want to restart your apache, with a command similar to:
sudo apachectl restart
You might clear your browser cache every time that you make a change on .htaccess file
Graph
This graph shows how your expression works, if you wish to know:
This tool can help you to simply design any rule that you like to have.
I have assumed that you want to redirect all your ?lang=en containing ULRs to a single URL. I was not sure about that. If that's not the case, you may not use my expression.

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]

Htaccess Regex won't match

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]

mod_rewrite with nested .htaccess files

I have made an .htaccess to my root directory for creating a subdomain level, assume it is sub.domain.ex that redirect to domain.ex/deb/
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} sub.domain.ex
RewriteCond %{REQUEST_URI} !deb/
RewriteRule ^(.*)$ /deb/$1 [L]
and this works well.
Now, I go to /deb/ and create another .htaccess with the following
RewriteEngine on
RewriteRule ^([^/]+)/ /deb.php?app=$1 [NC]
the deb.php is a file that prints the argument "app".
It works but only if i call http://sub.domain.ex/something/ (note the slash at the end). It only works with a final slash, if I remove it, it doesn't and I want it to work without final slash.
So I change the rule into ^([^/]+) but now I have 500 Apache internal error.
The regex coaches are by my side with the selection, maybe I'm missing something.
Thanks
UPDATE
I'm runinng mad. Mybe is wrong to put one .htaccess in the root for creating se 3th sublevel doman and the .htacces in the other directory? Because I'm ttrying some trick.
I use this rule
RewriteEngine on
RewriteRule ^([^/]+)/ deb.php?app=$1 [NC]
in the .htacces of the /deb directory and made a print_r($_GET); and called index.php. So the redirectory doesn't work at all if it forward me on the index.php of the cydia sublvel and doesn't take the /deb/deb.php!!!
Recap.
my dir structure is this:
/htdocs/ -> the root of the main domain level like www.example.com
---index.php -> home file of www.example.com
/htdocs/deb -> the root directory of the 3th sublevel domain (subdomain.example.com ->
---index.php
---deb.php
So the .htaccess for the 3th level domain is the in /htdocs./htaccess and described as before.
The other .htaccess for "beautify" the link is in the /htdocs/deb/.htaccess. I want that when you go to subdomain.domain.com/someText it transform to deb.php?app=someText
Now i tryed go to subdomain.domain.com/deb.php....WTF!? the deb.php is in /htdocs/deb/deb.php
Home is clear
This works fine for me, at least, assuming I understood everything you wanted.
In /htdocs/.htaccess:
RewriteEngine On
RewriteCond %{HTTP_HOST} =sub.domain.ex
RewriteCond %{REQUEST_URI} !^deb/
RewriteRule ^(.*)$ /deb/$1
In /htdocs/deb/.htaccess:
RewriteEngine On
RewriteBase /deb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/?$ deb.php?app=$1
RewriteRule !^deb.php index.php
Edit: I updated the second file's contents to reflect your additional requests. You should remove the /? if you don't want them to be able to go to sub.domain.ex/something/ -> deb.php?app=something.
I could be wrong, but in the second .htaccess you should check that the url wasn't yet rewrited with "/deb.php"
So something like
RewriteCond %{REQUEST_URI} !deb\.php
RewriteRule ^([^/]+) /deb.php?app=$1 [NC]
You rewrite rule should be
RewriteRule ^(.*)$ deb.php?app=$1 [L,QSA]
That's a common pattern used in CMSs like Drupal
I think there is some kind of rescrctions to my host. It's impossible. I tried all kind of goo (for a regexcoach) for matching the correct group and there is nothing else the 500 error apache.
The only way to get this to work is use tu parameters
with this ^app/([^/]+) /deb.php?app=$1 and calling with sub.domain.com/app/nameTest and this is working with or without the end backslash.
Of you get some advice for getting rid of this, please let me know.
bye