Apache Redirect problem in .htaccess - apache

I am having problems getring a simple redirect statement to take effect on my Godaddy account. I have the following statements in my .htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.mydomain.net$ [NC]
RewriteRule ^(.*)$ http://mydomain.net/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^mydomain.net$ [NC]
RewriteRule ^/lists/$ / [R=301]
RewriteCond %{HTTP_HOST} ^mydomain.net$ [NC]
RewriteRule ^/blog/$ http://myotherdomain.net/ [R=301]
The 1st redirect ALWAYS work. The 2nd and 3rd ones however, NEVER work. I just get a 404 from the server. The Apache logs do not reveal any useful infomation - just a 404.
Any ideas, anybody?
Your help will be greatly appreciated.
Thanks

Per-directory Rewrites
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done.
– http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule
So just leave the leading slash out of the pattern.

For simple redirects like that, better use the simple RedirectMatch directives:
RedirectMatch 301 ^/lists/$ http://mydomain.net/
RedirectMatch 301 ^/blog/$ http://myotherdomain.net/
If you insist on using rewriting make sure you add the L flag to your rules.
Apache mod_rewrite Flags says :
You will almost always want to use [R] in conjunction with [L] (that is, use [R,L]) because on its own, the [R] flag prepends http://thishost[:thisport] to the URI, but then passes this on to the next rule in the ruleset, which can often result in 'Invalid URI in request' warnings.

Simply remove the slashs at the beginning. It also might be useful to make the slashs at the end optional.
RewriteCond %{HTTP_HOST} ^mydomain.net$ [NC]
RewriteRule ^lists/{0,1}$ / [R=301]
RewriteCond %{HTTP_HOST} ^mydomain.net$ [NC]
RewriteRule ^blog/{0,1}$ http://myotherdomain.net/ [R=301]

Put the first one last. Once it encounters a redirect match, it runs it and ignores the rest.

Related

Apache Redirect // to no //

An email went out with the wrong link (https://www.digitalmarketer.com/digital-marketing/content-marketing-strategy//) and we need to redirect the // to (https://www.digitalmarketer.com/digital-marketing/content-marketing-strategy/) but no matter what I try, the redirect isn't working.
They also want it to be redirected to always have https:///www at the beginning and to never have index.html at the end, so already in the .htaccess file I have:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteRule ^content\-marketing\-strategy/index\.html$ /digital-marketing/content-marketing-strategy/? [L,R=301]
I've tried adding a new RewriteRule, but this won't work:
RewriteRule ^content\-marketing\-strategy//$ /digital-marketing/content-marketing-strategy/? [L,R=301]
I'm very new to Apache and redirects so any help is much appreciated! Thank you!
Edit: Of note, this is in an .htaccess file inside of the digital-marketing folder (https://www.digitalmarketer.com/digital-marketing/.htaccess) which was done so all the above rules would only apply to the digital-marketing folder.
You can use insert rule at the end of your other rules to strip multiple // into /:
RewriteCond %{THE_REQUEST} //
RewriteRule ^.*$ /digital-marketing/$0 [R=301,L,NE]
Apache automatically strips down multiple // into one inside the pattern for RewriteRule thus captured value $0 will have all // converted into /
You can write a wildcard expression to remove trailing slashes. The below will match any HTTP or HTTPS URL that trails in a forward slash, and remove all trailing forward slashes from that URL:
RewriteRule ^(.*)/+$ $1 [R=301,L]
And more using 301 redirects, see more here: Best Practice: 301 Redirect HTTP to HTTPS (Standard Domain)
Good luck!
I see nothing in the way that the rule is written that would make it not rewrite. However you have multiple rules with the L flag that might stop processing on the rewrite at an earlier point than you are looking for. From the documentation
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.
(https://httpd.apache.org/docs/current/rewrite/flags.html).
You can try this page out http://htaccess.mwl.be/ to test all your rules together. You might have to rewrite them a bit to work with that page, it's not aware of the level your .htaccess file is at so you will have to rewrite all your rules to trigger from the root for example: RewriteRule ^digital\-marketing/content\-marketing\-strategy//$ /digital-marketing/content-marketing-strategy/? [L,R=301]

Rewrite condition to particular URL and redirect

I have a redirect rule that redirects a url of pattern /abcd/* to http://myweb.com/abcd/*.
I want to apply this redirect except /abcd/index.html.
I have tried this.
RewriteCond %{THE_REQUEST} !^/abcd/index
RewriteCond %{REQUEST_URI} !^/abcd/index [NC]
RewriteRule ^/abcd/(.+)$ http://myweb.com/abcd/$1 [NC,R=301,L]
I am not sure if it is correct.
Please suggest me the correct way of doing this.
Try this rule without leading slash in RewriteRule:
RewriteCond %{REQUEST_URI} !^/abcd/index [NC]
RewriteRule ^abcd/(.+)$ http://myweb.com/abcd/$1 [NC,R=301,L]
Difference is ^abcd/(.+)$ instead of ^/abcd/(.+)$
Your 2 conditions were redundant so I reduced it to one.
.htaccess is per directory directive and Apache strips the current directory path (thus leading slash) from RewriteRule URI pattern.

How to avoid chain redirections using mod_rewrite?

Basicly i'm working on my site to be SEO-friendly. I wanted to achieve following:
Rewrite urls to pretty ones
Remove multiple slashes (eg. example.com/////something/// to example.com/something/
Redirect www version to a non-www version.
Hide index.php file from all urls
Redirect from old (/?id=something/ to new urls /something/)
I came up with this .htaccess code:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
RewriteRule ^index.php(.*)$ /$1 [R=301]
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
...and though it's working it has a side effect: chain redirects, eg. example.com/?id=something////// -> example.com/something////// -> example.com/something/
So is there a way to rewrite or modify this code so it'll be redirecting just once to the preferred version of the url?
Trying to interpret what you want, let's look at the rules in your question:
.1 Can't understand the purpose of this:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
.2 This rule-set in your question removes www and converts the query string ?id=val to /val, but only when the incoming URI has www AND there is a query string as both conditions must be met:
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
.3 This rule
RewriteRule ^index.php(.*)$ /$1 [R=301]
Hides index.php, but only when it is in the root directory. Example:
http://www.example.com/index.php?id=val
Does not work when it is in a subdirectory. Example:
http://www.example.com/folder/index.php?id=val
.4 Can't understand the purpose of this:
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
I suggest this instead:
RewriteEngine On
RewriteBase /
#Redirects all www to non-www
RewriteCond %{HTTP_HOST} www\.example\.com$ [NC]
RewriteRule ^(.*)/?$ http://example.com/$1 [R=301,L]
#Hides "index.php" keeping the query if present
RewriteRule ^(.*)/index\.php$ $1/ [R=301,QSA,L]
#Converts query string `?id=val` to `/val`
RewriteCond %{QUERY_STRING} id=([^/]+)
RewriteRule .* /%1? [R=301,L]
Remember spiders will "adapt" to the correct new structure after a few months, and the problem may ultimately be a whole lot less severe than what it looks like initially. You can leave all the .htaccess code in place, knowing it always be there to correct any "old" references yet will in fact hardly ever actually be used.
I've never found an easy way to avoid multiple round trips back to the client when "fixing up" a URL to be in some sort of canonical form. mod_rewrite seems to be more focussed on the "local" redirect case where the client has no idea that the content it got back came out of a file structure that doesn't perfectly match that implied by the URL.
It is possible to save up all the URL mods locally, then provoke only one round trip to the client that delivers all the URL corrections all at once by setting everything in newly created "environment" variables then at the end asking basically "has anything changed?" However doing so is notably verbose and rather awkward and quite error-prone and has never become a "recommended technique".

Can't get mod_rewrite to correctly (and invisibly) re-write my URLs?

I'm trying to make a URL shortening service for my website.
So instead of:
http://www.myfullwebsitename.com/page78/this-is-a-headline/
users will be able to visit:
http://abc.de/aBxf
which needs to redirect (invisibly!) to
http://abc.de/?shorturl=aBxf
which then 301 redirects via a database lookup to
http://www.myfullwebsitename.com/page78/this-is-a-headline/
I can do the DB lookup and the 301 redirect easily. It's the invisible intermediate redirect that I'm struggling with.
I've tried a LOT of different things, but none seems to work. This is what I currently feel should work:
RewriteCond %{HTTP_HOST} ^abc.de
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^/(.+) /?shorturl=$1
But instead of redirecting silently to
http://abc.de/?shorturl=aBxF
it redirects "noisily" (302) to
http://abc.de/aBxF/?shorturl=aBxF
What am I doing wrong?
Thank you!
There's a few things you can try.
I think your RewriteRule should look like this (without the forward /):
RewriteRule ^/(.+) ?shorturl=$1 [L]
This should at the very least stop it from redirecting to http://abc.de/aBxF/.
Your original rule may work if you add:
RewriteBase /
If it were me my rules would actually look like this:
RewriteBase /
RewriteCond %{HTTP_HOST} ^abc.de$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /redirect.php [L]
And then in PHP I would use $_SERVER['REQUEST_URI'] to get the URL (not sure what language you're using).
The rule can look like this:
RewriteRule ^(.*)$ /redirect.php?shorturl=$1 [L]
But I would make sure to mention the script by name. Part of what may be throwing your rules off is relying on Apache finding your index file after a rewrite.
The way Apache's rewrite rules work is as soon as the URL is rewritten, it actually will re-run the rules until no other rules will be found. The [L] flag for "last" says "stop here" - but it still starts over from the top. The RewriteCond with the !-f flag says "only if the file doesn't exist".
Use an absolute URL:
RewriteCond %{HTTP_HOST} ^abc.de
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ http://abc.de/?shorturl=$1 [R=301,L]

htaccess - rewritecond issue

I have an htacess file for apache that isn't working properly.
I have a default cactch-all that grabs all requests however it's still catching the matched URL above it (ajax/*). I thought that condition to match urls not containing ajax would stop it but it isn't.
RewriteRule ^ajax/(.*)$ process_lite.php [QSA,L]
RewriteRule ^resources/(.*)$ resources/$1 [L]
RewriteCond %{REQUEST_URI} !\.(css|jpg|js|gif|png)$
RewriteCond %{REQUEST_URI} !^ajax
RewriteRule ^(.*)$ process.php [QSA,L]
Can someone help me out?
It's probably because the first rule matches /ajax/ requests and rewrites it to /process_lite.php, thus the RewriteCond %{REQUEST_URI} !^ajax doesn't match since the URI is now process_lite.php. The regular expression you use won't match anything anyways because REQUEST_URI variable will start with a leading slash. You can try changing the condition to:
RewriteCond %{REQUEST_URI} !^/process_lite.php
Additionally, the "resources" rule doesn't seem to do anything except end rewriting, you could change it to this if that's the goal:
RewriteRule ^resources/ - [L]