How to simulate directories with a htacess file (mod_rewrite)? - apache

what I try to do is to simulate directories with the help of a htaccess file.
I have a website with a file like this:
http://www.domain.com/filename.php?t=yeah-a-title-2014
Now, I would like to rewrite the URL above to the following:
http://www.domain.com/directory1/yeah-a-title-2014/
If a visitor enters one of the two URLs, he should see the second one in his address bar but the content of the filename.php?t=yeah-a-title-2014 should be displayed.
I have no idea how to realize this.
Any ideas?

This is better known as SEO-urls (search engine optimized), SEF-urls (search engine friendly), fancy urls and a couple more of those terms. The basic problem with these kind of constructions, is that they cause an infinite loop if not implemented correctly, and therefore usually the THE_REQUEST trick is used, because %{THE_REQUEST} is always equal to the request, even if the url is rewritten, which in turn prevents the external redirect from matching if the internal rewrite matches.
#External redirect
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /filename\.php\?t=(.*)\ HTTP
RewriteRule ^ /directory1/%2/ [R,L]
#Change [R,L] to [R=301,L] after ALL rules do what you want them to do, and before your site goes live
#Internal rewrite
RewriteRule ^directory1/([^/]+)/?$ /filename.php?t=$1 [L]

Related

mod_rewrite: hide real urls but keep available as different files

Possible this question has already been answered but I didn't find any answer after hours of searching.
I need to put the site under "maintenance mode" and redirect/rewrite all requests to site_down.html, but at the same time I need the site to be available if I enter the address like files are in a subfolder.
ex:
if I type http://example.com/login.php I need site_down.html to be displayed.
but if I specify http://example.com/test/login.php I need real login.php do be displayed.
I need this to be done with rewrite, so copying everything to another directory isn't a solution.
I tried a couple dozens of combinations, but I'm still unable to achieve what I need
This is one version of my .htaccess file ():
DirectoryIndex site_down.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^test\/(.*)$ $1 [S=1]
RewriteRule ^(.*\.php)$ site_down.html
RewriteRule .* - [L]
</IfModule>
This code should rewrite all requests with "test/*" to "parent folder" and skip next rewrite rule and then terminate rewriting at RewriteRule .* - [L]. If there is no "test/" in url - all request should be rewritten to site_down.html
What am I doing wrong?
Could you suggest any valid solutions, please?
Thank you.
Essentially, you are searching for 2 rules. One rule will translate a virtual subdirectory to the working files. The other rule will translate the url to the working files to a splash page. We just have to make sure that if the first rule matches, the second rule doesn't match. We can do this by making sure " /test/" (including that leading space) was not in THE_REQUEST (or the string that the client sent to the server to request a page; something in the form of GET /test/mypage.php?apes=bananas HTTP/1.1). THE_REQUEST doesn't change on a rewrite, which makes it perfect for that. Skipping a rule like you did usually doesn't have the effect you expect, because mod_rewrite makes multiple passes through .htaccess until the resulting url doesn't change anymore, or it hits a limit and throws an error. The first time it will skip the rule, but the second time it will not do that.
RewriteCond %{THE_REQUEST} !\ /test/
RewriteRule \.php site_down.html [L]
RewriteRule ^test/(.*)$ $1 [L]

htaccess page to page redirect and seo friendly urls

i have a problem with a htaccess files and i cannot figure it what is the problem.
The site has url rewriting for seo purposes in place so:
www.website.com/page/seo-friendly-url
is rewritten to
www.website.com/page.php?seo=seo-friendly-url
this is done with the following
RewriteEngine on
RewriteBase /
Rewriterule ^page/([a-zA-Z0-9_-]+)$ page.php?seo=$1 [NC,L]
Now the problem is that i have to redirect some pages that are already indexed by the search engines to their new destination as they are no more available, for example:
www.website.com/page/seo-friendly-url
has to be redirected to
www.website.com/page/another-seo-friendly-url
I have tried something like this but it is not working
Rewriterule ^page/seo-friendly-url$ page/another-seo-friendly-url [R,NC,L]
also this one is not working
Rewriterule ^page/seo-friendly-url$ page.php?seo=another-seo-friendly-url [R,NC,L]
This seems pretty stupid but i can't find the problem :-/
Thank you for your help
Ema
Edit, for anubhava:
Hi,
no i have already set the rewriting for that.
What i'm trying to achieve is redirect an already rewrited link.
Let me explain myself better:
At the moment i have this url that is indexed by Google (or any other search engine) in the form of a beautified url (seo friendly). The url has this form:
www.website.com/page/seo-friendly-url
I have already set a rule in the htaccess so the previous link is rewritten and goes to a php page with a query string that is used to display some content.
The page and the query are in this form:
www.website.com/page.php?seo=seo-friendly-url
So basically i'm using the last part of the first url as a query parameter for the second url.
This is achieved (and works) through the following code here below:
RewriteEngine on
RewriteBase /
Rewriterule ^page/([a-zA-Z0-9_-]+)$ page.php?seo=$1 [NC,L]
So far so good.
Now what i need to achieve is to redirect this url, that has been deleted:
www.website.com/page/seo-friendly-url
to go to a new page
www.website.com/page/another-seo-friendly-url
Of course the same rules applies to this new url (www.website.com/page/another-seo-friendly-url -->is already rewrited to--> www.website.com/page.php?seo=another-seo-friendly-url)
What do i need to do to do the reewriting right?
Thanks
You need this extra rule before your existing rule:
RewriteEngine on
RewriteBase /
RewriteCond %{THE_REQUEST} \s/+page\.php\?seo=([^\s&]+) [NC]
RewriteRule ^ /page/%1? [R=301,L]
Rewriterule ^page/([\w-]+)$ page.php?seo=$1 [NC,L,QSA]
Just add redirects like this:
RewriteRule page/seo-friendly-url /page/new-url [R=301,L]
Important: this rules have to be above your existing rewrites because of the L flag in your rewrites
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed.
http://httpd.apache.org/docs/current/rewrite/flags.html#flag_l
Edit
You want to redirect the old URL to avoid duplicate content (rewrite=internal, redirect=HTTP 301)
Maybe you are open for solutions thinking in another direction.
I would try to handle this in the application, no through rewrites. Right now the GET parameter seo is handled in page.php. Isn't it an idea to extend this in that way one product can be identified through multiple seo aliases? If one product has to be taken off a similar one will then own this alias (simply a change of one row in the database).
As I don't know what software you are using this may be not possible.

How to prevent mod_rewrite from rewriting URLs more than once?

I want to use mod_rewrite to rewrite a few human-friendly URLs to arbitrary files in a folder called php (which is inside the web root, since mod_rewrite apparently won't let you rewrite to files outside the web root).
/ --> /php/home.php
/about --> /php/about_page.php
/contact --> /php/contact.php
Here are my rewrite rules:
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^$ php/home.php [L]
RewriteRule ^about$ php/about_page.php [L]
RewriteRule ^contact$ php/contact.php [L]
However, I also want to prevent users from accessing files in this php directory directly. If a user enters any URL beginning with /php, I want them to get a 404 page.
I tried adding this extra rule at the end:
RewriteRule ^php php/404.php [L]
...(where 404.php is a file that outputs 404 headers and a "Not found" message.)
But when I access / or /about or /contact, I always get redirected to the 404. It seems the final RewriteRule is applied even to the internally rewritten URLs (as they now all start with /php).
I thought the [L] flag (on the first three RewriteRules) was supposed to prevent further rules from being applied? Am I doing something wrong? (Or is there a smarter way to do what I'm trying to do?)
[L] flag should be used only in the last rule,
L - Last Rule - Stops the rewriting process here and don’t apply any more rewriting rules & because of that you are facing issues.
I had similar problem. I have a content management system written in PHP and based on Model-View-Control paradigm. The most base part is the mod_rewrite. I've successfully prevent access to PHP files globally. The trick has name THE_REQUEST.
What's the problem?
Rewriting modul rewrites the URI. If the URI matches a rule, it is rewritten and other rules are applied on the new, rewritted URI. But! If the matched rule ends with [L], the engine doesn't terminate in fact, but starts again. Then the new URI doesn't more match the rule ending with [L], continues and matches the last one. Result? The programmer stars saying bad words at the unexpected 404 error page. However computer does, what you say and doesn't do, what you want. I had this in my .htaccess file:
RewriteEngine On
RewriteBase /
RewriteRule ^plugins/.* pluginLoader.php [L]
RewriteCond %{REQUEST_URI} \.php$
RewriteRule .* index.php [L]
That's wrong. Even the URIs beginning with plugins/ are rewritten to index.php.
Solution
You need to apply the rule if and only if the original - not rewritten - URI matches the rule. Regrettably the mod_rewrite does not provide any variable containing the original URI, but it provides some THE_REQUEST variable, which contains the first line of HTTP request header. This variable is invariant. It doesn't change while rewrite engine is working.
...
RewriteCond %{THE_REQUEST} \s.*\.php\s
RewriteRule \.php$ index.php [L]
The regular expression is different. It is not applied on the URI only, but on entire first line of the header, that means on something like GET /script.php HTTP/1.1. But the critical rule is this time applied only if the user is explicitly requesting some PHP-script directly. The rewritten URI is not used.

301 redirect query string to SEO friendly URLs through .htaccess

I’ve written some code on my .htaccess file which allows the use of SEO friendly URLs instead of ugly query strings. The following code rewrites the SEO friendly version in the browser to the query string version on the server.
RewriteEngine On
RewriteRule ^seo/([^/]*)/$ /directory/script.php?size=large&colour=green&pattern=$1 [L]
So that the ugly
http://www.mysite.com/directory/script.php?size=large&colour=green&pattern=striped
Is now beautiful
http://www.mysite.com/directory/seo/striped/
Just to explain the code a bit; seo is there to add more keywords to the URL, /directory/ is the directory in which the .htaccess file is located, parameters size=large and colour=green never change, while pattern=$1 can be many different values.
The above code works perfectly. However, the problem is I am now stuck with two URLs that point to exactly the same content. To solve this, I would like to 301 redirect the old, ugly querystrings to the SEO friendly URLs. What I have tried so far does not work - and Google is not being particularly friendly today.
Can anybody offer working code to put in my .htaccess file that redirects ugly to new URL, while retaining the rewrite? Thanks!
This should do the trick:
RewriteEngine On
## Redirect to pretty urls
# The '%1' in the rewrite comes from the group in the previous RewriteCond
RewriteCond %{REQUEST_URI} !seo
RewriteCond %{QUERY_STRING} ^size=large&colour=green&pattern=([a-zA-Z]*)$
RewriteRule (.*) /directory\/seo\/%1\/? [L,R=301]
## Rewrite to long url, additional parameter at the end will cause
## the internal redirect not to match the previous rule (would cause redirect loop)
RewriteRule ^directory\/seo\/([^/]*)/$ /directory/script.php? size=large&colour=green&pattern=$1&rewrite [L]
You can also match the size and colour if needed, by changing those to regex groups as well, and using the corresponding %N
Hope this helps.
Not tested, but this may work...
RewriteRule ^directory/script.php?size=large&colour=green&pattern=(.*)$ /seo/$1/? [R=301,NE,NC,L]

.htaccess redirect doesn't hide url

my .htaccess in the root folder includes the following lines :
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ http://example.com/?city=$1 [NC]
when I open the address http://example.com/bla.htm, my browser doesn't hide the GET values specified in the .htaccess, it redirects me to ?city=bla. eventhough I'm not using the [R] switch. This has always worked for me before (as I remember, haven't dealt with htaccess in a while). What's wrong here ?
When you redirect to an entire URL, it doesn't do URL rewriting (you can't exactly rewrite URLs on someone else's website).
Assuming both URLs are on the same server, you need to do something like
RewriteRule ^(.*)\.htm$ index.php?city=$1 [NC]
Also, I'd recommend getting into the habit of using the [L] switch whenever you can - it helps avoid bugs when you have a lot of URLs to rewrite.