htaccess - Redirect loop - .htaccess

Why is this causing a redirect loop?
Options +FollowSymlinks
RewriteEngine on
RewriteBase /summary/1/document/
RewriteRule !^[a-z]{2}/ /summary/1/document/en/ [L,R]
RewriteRule ^([a-z]{2})/ ../index.php?lang=$1&type=document
What I am trying to achieve is:
If there's no language specified, redirect to english:
Example:
website.com/summary/1/document --> website.com/summary/1/document/en/
website.com/summary/1/document/fr/ [no redirect]
And when a language is specified, rewrite internally to ../index.php with lang and type parameters.

From Flag L: Apache Docs: flag_l :
If you are using RewriteRule in either .htaccess files or in <Directory> sections, it is important to have some understanding of how the rules are processed. The simplified form of this is that once the rules have been processed, the rewritten request is handed back to the URL parsing engine to do what it may with it. It is possible that as the rewritten request is handled, the .htaccess file or section may be encountered again, and thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect - either internal or external - causing the request process to start over.
Since, rewritten request is handed back to the URL parsing engine, after redirect from the first rewrite rule,
Try this:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /summary/1/document/
RewriteRule ![a-z]{2}/$ /summary/1/document/en/ [NC,L,R]
RewriteRule ^([a-z]{2})/$ ../index.php?lang=$1&type=document [L,QSA]

Related

htaccess block original file however allow rewrite

I have the following entries in my /.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^signin.php - [L,gone]
RewriteRule ^sign-in/?$ /signin.php [L]
What I am trying to achieve is to allow the user to access /sign-in but not the original file /signin.php
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
Thanks for any help.
To redirect any direct requests for /signin.php to /sign-in and internally rewrite /sign-in back to /signin.php then you can do it like this:
RewriteEngine On
RewriteRule ^signin\.php$ /sign-in [R=301,L]
RewriteRule ^sign-in$ signin.php [END]
The END flag (Apache 2.4) prevents any further loops by the rewrite engine, so prevents the rewritten URL being redirected back to /sign-in, which would otherwise cause a redirect loop.
The END flag is not required on the first rule, since an external redirect will trigger immediately. (The L flag is still required.)
You do not need the RewriteBase directive here.
I removed the optional trailing slash on /sign-in as this potentially creates a duplicate content issue. If you wish to allow an optional trailing slash then redirect to the canonical URL (without the trailing slash, or with if you prefer) instead.
UPDATE:
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
The Apache solution in the referenced answer is not quite correct. The answer would seem to have been "accepted" for the first part regarding doing this in PHP instead.
At the time of that question (2011), they would have been using Apache 2.2. The END flag was only introduced in Apache 2.4.
They would have needed to have done it like this, to prevent a redirect loop:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^about.php /about [L,R=301]
RewriteRule ^about$ about.php [L]

URL rewrite on core PHP

I want to rewrite URL from
example.com/file.php?id=yes
To
example.com/file.php/yes
Website is on core PHP
I have tried the below code in .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([0-9]+).html /abc.php?id=$1 [QSA,L]
Yes, I have, Now I just want to redirect example.com/file.php?id=yes to example.com/file.php/yes
In order to preserve SEO, having changed the URL structure you could implement an external redirect like this, at the top of your .htaccess file:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=(\w+)
RewriteRule ^file\.php$ /$0/%1 [QSD,R=301,L]
The $0 backreference contains the complete match from the RewriteRule pattern (ie. file.php). And the %1 backreference (note the %) contains the value of the id URL parameter from the preceding CondPattern.
The QSD flag is necessary to discard the original query string from the redirected request.
Note you should test first with a 302 (temporary) redirect in order to avoid potential caching issues.
Aside:
Actually i want to do it due to cosmetic reason and also make this SEO friendly
Although, there's not really any difference SEO-wise between these two URLs. In fact, simply changing the URL structure you could have a short term negative effect on SEO.
RewriteRule ^([0-9]+).html /abc.php?id=$1 [QSA,L]
This appears to do the opposite and something quite different from your intended action...
It would internally rewrite (not "redirect") a URL of the form /0123456789.html?foo=1 to /abc.php?id=0123456789&foo=1

trouble with simple mod_rewrite redirect rule

I have mod_rewrite working in a development environment.
This testing domain is using these rules in an .htaccess file:
Options +FollowSymLinks
Options +Indexes
RewriteEngine on
# deal with potential pre-rewrite spidered / bookmarked urls
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
# deal with actual urls
RewriteRule ^clothes/[0-9a-z-]+-pr([0-9]+).php$ /clothes/product.php?pid=$1 [L]
The 2nd Rule works fine. Entering http ://testdomain.dev/clothes/shirt-pr32.php is silently delivered content from http ://testdomain.dev/clothes/product.php?pid=32 ...which is as desired and expected!
However, assuming this was applied to a live site, one that had originally used paths such as: http ://testdomain.dev/clothes/product.php?pid=32, I'd like to redirect any incoming requests following the old pattern to the new urls ...which is what the 1st Rule was intended to do.
My problem is my testing server seems to ignore the 1st Rule and serves the page as requested (page loads but address bar remains at http ://testdomain.dev/clothes/product.php?pid=32)
Any assistance or enlightenment would be most graciously accepted!
You need to match the query string within a RewriteCond, then backreference that RewriteCond from the rule. The RewriteRule only matches against the path, not the query string.
Here's a related post I previously answered with a similar request: Mod_rewrite rewrite example.com/page.php?v1=abc&v2=def to example.com/abc/def
You can't match against the query string in a rewrite rule, you need to use the `%{QUERY_STRING} variable in a condition and use the % to backrefernce groupings. So instead of:
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
You'll need:
RewriteCond %{QUERY_STRING} ^pg=([0-9]+)
RewriteRule ^clothes/index.php$ /clothes/index%1.php? [R=301,L]

Sitewide 301 Redirect with a subset of different redirects

I am trying to make a sitewide 301 redirect for a site with around 400 pages but also have a subset of about 10 individual pages that don't follow the sitewide redirect and should point somewhere else.
Any ideas how to format such redirect rules so the sitewide redirect doesnt conflict with the subset pages redirect?
I am starting with the sitewide redirect rule as:
Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*) http://www.name.com/$1 [R=301,L]
The rewrite rules are parsed in the order they are written, so the order you list them also defines the priority.
Given that, you should first match the request URI with the 10 individual pages and return the redirection accordingly, and then define the sitewide redirection.
If the 10 individual pages have a single target URL, the match rule may be one, otherwise you should do a single redirection per each request URI.
Take care to use the [L] flag for the first redirections, to tell the server to exit the routine if the rule is matched, and I would also suggest to add the line
RewriteBase /
which is pivotal for some Apache versions, in which the omission of this line may cause a http bad conf error.
Options +FollowSymLinks
#switch on the rewrite engine:
RewriteEngine On
RewriteBase /
#rules for the individual redirections:
RewriteRule http://example.com/myUrl-1 http://www.example.org/new-1 [R=301,L]
RewriteRule http://example.com/myUrl-4 http://www.example.org/new-2 [R=301,L]
RewriteRule http://example.com/myUrl-3 http://www.example.org/new-3 [R=301,L]
#...and so on
#sitewide redirection rule:
RewriteRule (.*) http://www.example.org/$1 [R=301]

URL rewrite issues using .htaccess

I'm trying to write a URL like below, but when I try to call the seo queryparam, it always returns index.php. Any idea why it isn't returning the correct value for 'seo'?
RewriteRule ^([^/]*)$ index.php?c=home&m=details&seo=$1 [L]
The URL it should forward from would be something like this: http://domain.com/The-Name-of-the-Product. That URL should be rewritten to http://domain.com/index.php?c=home&m=details&seo=The-Name-of-the-Product, but instead it ends up as http://domain.com/index.php?c=home&m=details&seo=index.php
Various events cause a URL to go back through the rewrite process. You can use RewriteCond to prevent this:
RewriteCond $1 !^index.php$
RewriteRule ^/?([^/]+)$ index.php?c=home&m=details&seo=$1 [L,NS]
From the mod_rewrite technical details:
When you manipulate a URL/filename in per-directory context mod_rewrite first rewrites the filename back to its corresponding URL (which is usually impossible, but see the RewriteBase directive below for the trick to achieve this) and then initiates a new internal sub-request with the new URL. This restarts processing of the API phases.
This catches people all the time.

Resources