htaccess redirect from top to subdirectory - regex

I have a web server with the following (simplified) layout:
/
www/ # will hold html and PHP files (web content)
doc/ # some documentation
lib/ # some libraries
I would like to use htaccess to "redirect" every request to www.mydomain.com/page to www.mydomain.com/www/page.php.
I have tried the following:
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^(.*)$ www/$1.php
But it produces a 500 Internal Server Error.
For debugging purposes, I created a www/test.php page which echoes every GET variable, and I modified my .htaccess:
RewriteRule ^(.*)$ www/test.php?page=$1
just to check whether I'm matching the right things.
The expected behaviour when performing a request against www.mydomain.com/somepage would be page=somepage, instead I get page=www/get.php.
Why this behaviour? How can I accomplish what I need?

You have to exclude the path you are rewriting to :
RewriteRule ^((?!www).*)$ www/test.php?page=$1 [NC,L]
otherwise you will get an infinite loop error because www/test.php also matches the rewrite pattern (.*)

Related

Yet another mod_rewrite query -- Cannot rewrite to pretty url and keep query strings

I'm literally at the end of my tether with this. I've researched many other questions and answers on stackoverflow but still can't find the solution i need. I'm starting to think what i want to do is not possible.
So... the problem is this. I want to turn the following:
e.g.
www.mydomain.com/visa-information/country.php?country={COUNTRY-NAME}&passport={PASSPORT-NAME}
To the following pretty url:
www.mydomain.com/visa-information/{COUNTRY-NAME}-visa-for-{PASSPORT-NAME}-citizens/
I have a partially successful rule in my htacces file as so:
RewriteRule ^/visa-information/([A-Za-z-]+)-visa-for-([A-Za-z-]+)-citizens/?$ visa-information/country.php?country=$1&passport=$2 [NC]
which works fine and does what i want if i enter the url into the browser address bar, but the real problem i'm having is getting it to re-direct to the pretty url via a form i have on pretty much every page of the site.
I've tried various re-direct rules like the one below:
RewriteCond %{QUERY_STRING} country=([A-Za-z-]+)&passport=([A-Za-z-]+) [NC]
RewriteRule visa-information/country.php visa-information/%1-visa-for-%2-citizens/? [R,NC,L]
But no luck. I've also tried adding the QSA flag to the above re-direct rule, but it just ends up with an endless loop.
I have tried using a location php re-direct header at the top of the country.php page to re-direct after form submission like so:
if(isset($_GET['country']) && isset($_GET['passport'])) {
header("Location: " . $dir . "/visa-information/" . $currentCountry . "-visa-for-" . $currentPassport . "-citizens/");
exit();
}
I was expecting the above to work like entering the pretty url directly into the browser works, but it doesn't, just gives me a 404 error.
Any help is greatly appreciated.
Thanks
Jordash
EDIT
My local directory structure is as follows:
/webserver/mydomain.com/visa-information/etc...
On the live server it will be:
mydomain.com/visa-information/etc..
As i am using an Apache Alias on my local machine i have set RewriteBase as:
RewriteBase /webserver/mydomain.com/
I currently have the following set of RewriteRules adapted from what anubhava gave me:
RewriteCond %{REQUEST_URI} visa-information/country.php [NC]
RewriteCond %{QUERY_STRING} country=([A-Za-z-]+)&passport=([A-Za-z-]+) [NC]
RewriteRule visa-information/ visa-information/%1-visa-for-%2-citizens/? [R=301,L,QSA]
# internal redirect from pretty URL to old URL
RewriteRule ^visa-information/([A-Za-z-]+)-visa-for-([A-Za-z-]+)-citizens/?$ visa-information/country.php?country=$1&passport=$2 [NC,L]
This currently gives me an endless re-direct loop, both when entering the pretty url in the browser bar, and when using my form, however if i disable the top 3 rules then i find i can enter the pretty url into the address bar and the rewrite works, but not from the form submission of course.
I really don't know what i'm doing wrong. Why is there an endless loop?
Not sure how first rule is working for you since RewriteRule doesn't match leading slash in .htaccess. Also to redirect old url to pretty URL you need to use THE_REQUEST variable that represents original request received by Apache from your browser. Replace your code with this:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# external redirect from old URL to pretty URL
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+visa-information/country\.php\?country=([^\s&]+)&passport=([^\s&]+)\s [NC]
RewriteRule ^ /visa-information/%1-visa-for-%2-citizens/? [R=301,L]
# internal redirect from pretty URL to old URL
RewriteRule ^visa-information/([a-z-]+)-visa-for-([a-z-]+)-citizens/?$ /visa-information/country.php?country=$1&passport=$2 [NC,L,QSA]
Looks like the issue was actually with my php form and not the mod_Rewrite rules. The form "action" was pointing to the same form page (as in $SERVER['PHP_SELF']) which works fine without the rewrite rules, but causes an endless loop when they are activated.
I simply made a search_action.php page and then redirect the form there using a php header to the pretty url:
header("Location: " . $dir . "/visa-information/" . $currentCountry . "-visa-for-" . $currentPassport . "-citizens/");
exit();
The mod_rewrite rule I had originally works fine and now the user can get to the desired page with the pretty url from the form or by tyoing directly into the browser address bar.
I'm not sure it's actually possible to action a form to the same page whilst rewriting the query string, without using an intermediary action page from the form, or Javascript. I'm sure many of the more experienced programmers will have known this already, but not me unfortunately.

.htaccess Subdirectory Rewrite Exception

I'm currently consolidating posts on a site we recently acquired that had multiple WordPress installs to manage content, one in the public_html folder and another in a subdirectory, like so:
1. http://domain.com/
2. http://domain.com/another-install/
We're moving all of the content from /another-install/ into the main setup, and using a 301 redirect to remove /another-install/ from all old links like so:
RedirectMatch 301 ^/another-install/(.*) http://domain.com/$1
Resulting in all articles redirecting like so:
http://domain.com/another-install/article-name/
TO
http://domain.com/article-name/
The problem is, we want to keep /another-install/ viewable as a page. With the current redirect, http://domain.com/another-install/ goes to http://domain.com/. Is there any way to add an exception, or rewrite the current rule so that it keeps /another-install/ viewable?
Change your regex from (.*) (which matches 0 or more of any character) to (.+) (which matches 1 or more of any character). That means there would have to be something following /another-install/ in order for there to be a redirect.
You need a RewriteRule to specify exclusions. Add this to your .htaccess file
RewriteCond %{REQUEST_URI} !^/old-install/(index\.wml)?$ [NC]
RewriteRule ^old-install/(.+)$ http://domain.com/$1 [R=301,NC,L]

URL rewrite - parameter is empty

I'm struggling to get a simple URL rewrite in my htaccess file to work. It looks like this:
RewriteRule ^getbars/([A-Za-z\d,]+)?$ getbars.php?guid=$1 [NC,L]
The idea is to redirect URLs such as /getbars/519f1dec603f9 to /getbars.php?guid=519f1dec603f9
For some reason, however, the guid parameter is empty when I try to get it in getbars.php
However, if I change it to
RewriteRule ^bars/([A-Za-z\d,]+)?$ getbars.php?guid=$1 [NC,L]
and load /bars/519f1dec603f9 in my browser instead, it seems to work OK.
What am I doing wrong?
Because the content negociation is enabled on your server (combined to PATH_INFO feature here)? If this is the case, the content negociation automatically "rewrites" getbars/* to getbars.php, before reading rewriting rules.
=> Can you try to add Options -MultiViews in your .htaccess?

RewriteCond %{QUERY_STRING} in mod_rewrite (dynamic to static URL) not working

As I have encountered very luck with managing to get querystrings to redirect correctly previously just passing querystring parameters, and the over-arching advice across this site and webmasterworld for querystring redirection seems to be "deal with it as a RewriteCond querystring", I'm trying to use the following type rule for a set of about 10 URLs.
Example URL:
http://www.example.org/training_book.asp?sInstance=1&EventID=139
What I have so far:
RewriteCond %{QUERY_STRING} ^training_book.asp\?sInstance=1&EventID=139
RewriteRule /clean-landing-url/ [NC,R=301,L]
So, what I want to happen is
http://www.site.org/training_book.asp?sInstance=1&EventID=139 301> http://www.site.org/clean-landing-url
but instead what is happening is this:
http://www.site.org/training_book.asp?sInstance=1&EventID=139 301> http://www.site.org/training_book.asp/?sInstance=1&EventID=139
It's appending a forward slash just before the querystring, and then resolving the full URL (obviously, 404ing.)
What am I missing? Is it a regex issue with the actual %{QUERY_STRING} parameter?
Thanks in advance!
EDIT -
Here's where I am so far.
Based upon the advice from #TerryE below, I've tried implementing the following rule.
I have a set of URLs with the following parameters:
http://www.example.org/training_book.asp?sInstance=1&EventID=139
http://www.example.org/training_book.asp?sInstance=2&EventID=256
http://www.example.org/training_book.asp?sInstance=5&EventID=188
etc.
which need to redirect to
http://www.example.org/en/clean-landing-url-one
http://www.example.org/en/clean-landing-url-two
http://www.example.org/en/clean-landing-url-three
etc.
This is the exact structure of the htaccess file I have currently, including the full examples of the "simple" redirects which are presently working fine (note - http://example.com > http://www.example.com redirects enforced in httpd.conf)
#301 match top level pages
RewriteCond %{HTTP_HOST} ^example\.org [NC]
RewriteRule ^/faq.asp /en/faqs/ [NC,R=301,L]
All URLs in this block are of this type. All these URLs work perfectly.
#Redirect all old dead PDF links to English homepage.
RewriteRule ^/AR08-09.pdf /en/ [NC,R=301,L]
All URLs in this block are of this type. All these URLs work perfectly.
The problem is here: I still can't get the URLs of the below type to redirect. Based upon advice from #TerryE, I attempted to change the syntax as below. The below block does not function correctly.
#301 event course pages
RewriteCond %{QUERY_STRING} sInstance=1EventID=139$
RewriteRule ^training_book\.asp$ /en/clean-landing-url-one? [NC,R=301,L]
The output of this is
http://staging.example.org/training_book.asp/?sInstance=1&EventID=139
(this is currently applying to staging.example.org, will apply to example.org)
(I had "hidden" some of the actual syntax by changing it to event_book from training_book in the initial question, but I've changed it back to be as real as possible.)
The the documentation. QUERY_STRING contains the request content after the ?. Your condition regexp should never match. This makes more sense:
RewriteCond %{QUERY_STRING} ^sInstance=1&EventID=139$
RewriteRule ^event_book\.asp$ /clean-landing-url/ [NC,R=301,L]
The forward slash is caused by a different Apache filter (DirectorySlash).

Mod Rewrite Regex - Match a url containting A but not B

I'm trying to send page requested through a front controller.
I need to match the following urls
domain.com/admin/
domain.com/admin/somepage
but I also have some assets in the /admin subfolder that I DONT want to match
domain.com/assets
domain.com/assets/mything.css
domain.com/assets/mything.css
domain.com/xml/myxml.xml
I have written the following rule (inside .htaccess in the root of the site and that works for all 5 example URLs. How do I get it to match the top two ONLY?)
RewriteBase /
# index.php is the front controller
RewriteRule ^(admin) admin/index.php [L,QSA]
There are two ways I can see of doing this (I'd like to know how to do it using the folder 'assets' and 'xml' as an exclusion AND by setting extensions)
I'd use a negative RewriteCond before the final routing rule along these lines:
RewriteCond %{REQUEST_URI} !assets