I want to set up redirects in htaccess from one domain to another but I've gone wrong somewhere - apache

I have a website, let's say fruit.com, and currently I have a bunch of redirects set up that work just fine, so for example fruit.com/apples/mcintosh will redirect to fruit.com/apples.php?id=mcintosh.
I also used to have some redirects set up to allow me to use a short URL, so fru.it/mcintosh would redirect to fruit.com/apples.php?id=mcintosh.
So far so good. A few years ago, though, my short domain lapsed and I didn't renew. Recently I've purchased it again and I'm interested in getting the same setup back.
Now, though, the redirects from the short domain to the main domain aren't working, although I've used exactly the same code, so I'm at a bit of a loss for what's going wrong.
RewriteCond %{HTTP_HOST} ^www\.fru\.it$
RewriteRule ^([0-9]+)$ "http\:\/\/www\.fruit\.com\/apples.php?id=$1" [R=301,L]

although I've used exactly the same code
But the code you've posted won't redirect the stated example URL fru.it/mcintosh, since the code matches digits only, not letters.
Try the following instead:
RewriteCond %{HTTP_HOST} ^www\.fru\.it
RewriteRule ^(\w+)$ http://www.fruit.com/apples.php?id=$1 [R=301,L]
The \w shorthand character class matches upper and lowercase letters, numbers and underscore.
You don't need all the backslash-escapes in the substitution string.
Also bear in mind that the order of these directives can be important. This rule would likely need to go near the top of the .htaccess file to avoid conflicts.
Test first with a 302 (temporary) redirect to avoid potential caching issues. Clear your browser cache before testing.
Aside:
fruit.com/apples/mcintosh will redirect to fruit.com/apples.php?id=mcintosh
It would seem to make more sense that this would be a (internal) "rewrite", not a (external) "redirect"? The shortcode would then redirect to fruit.com/apples/mcintosh, not fruit.com/apples.php?id=mcintosh?

Related

Redirecting Many Dynamic URLs (301)

I have a website that is generating dynamic URLs through categories and it outputs the same information on two separate URLs (In this example it's "buildings" and "houses")
I would like to redirect all URLs that have /buildings/ in the URL to the same one with /houses/ instead.
For example:
/buildings/united-states/arizona/tucson/
to
/houses/united-states/arizona/tucson/
There are many URLs like this and I would like to use a code that does this for all.
I have tried
RewriteRule ^buildings/(\d[^/]+) /houses/$1/ [R=301,L], but it didn't seem to work (it still pointed to the /buildings/ URL.
Appreciate all your comments and guidance, thank you!
RewriteRule ^buildings/(\d[^/]+) /houses/$1/ [R=301,L]
For some reason have a \d (shorthand character class) that matches digits 0-9 only, so this won't match the example URL. Also, [^/]+ would seem unnecessary if it can be followed by anything anyway.
Try the following instead:
RewriteRule ^buildings/(.*) /houses/$1 [R=302,L]
This matches /buildings/<anything>. The $1 backreference holds the <anything> part.
Test first with 302 (temporary) redirect to avoid potential caching issues and only change to a 301 (permanent) redirect once you have confirmed it works as intended. You should clear you browser cache before testing.
This needs to go near the top of your .htaccess file, before any existing rewrites.

Using .htaccess to control a 'parked' domain

My question is to ask if the level of domain name control I'd like with .htaccess is even possible, and how it might be achieved.
Here's the current situation. At the moment I have a main domain (call it primary.com) that has several language variants, under a file structure like
/lang/chinese
/lang/russian
etcetera. I decided to create a sub-domain for just one of them, so now I have china.primary.com. Of course I created a .htaccess file to make all variants of primary.com and www.primary.com point to the same place (www.primary.com), and now also china.primary.com points to www.primary.com/lang/chinese. Everything works well.
Next I added a second domain (secondary.com) as a 'parked' domain on the site. A little fight with .htaccess and now I have all requests for any version of secondary.com being rewritten as a call to www.primary.com. All good. Then comes the final finesse that is the nub of my question.
While I have anything.secondary.com point to www.primary.com at the moment, is it possible to add in an exception for the possible case where a user tries to access china.secondary.com? In that event I'd like it rewritten to china.primary.com and pointed at www.primary.com/lang/china.
Note I have not created a sub-domain china.secondary.com as my understanding is that it shouldn't be necessary. I think this either can or can't be done through .htaccess alone. Please excuse my iinexperience: what I have works but has been copy & pasted together as a result of finding various examples online. Here is what I have that works well right now - except the final line I added that because I hoped it would solve this, but it doesn't work.
Do I actually have to create a sub domain china.secondary.com for this to work? If so my goal is dead in the water since I cannot create a subdomain on a parked domain, I believe.
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^primary.com [NC]
RewriteRule ^(.*)$ http://www.primary.com$1 [L,R=301]
RedirectMatch 301 ^/lang/chinese/(.*)$ http://china.primary.com/$1
RewriteCond %{http_host} ^secondary\.com [nc]
RewriteRule ^(.*)$ http://www.primary.com/$1 [R=permanent,nc,L]
RedirectMatch 301 ^/lang/chinese/(.*)$ http://china.primary.com/$1
Steered in the right direction by Anubhava I researched this question even more. It seems a basic assumption of mine was incorrect. It looks like you do need to create a subdomain in order to steer people away from it with .htaccess. Seems deeply counter-intuitive to me, but there it is.
Of course I cannot create a sub-domain on a domain that is merely parked with a hosting company, so attempting to support users who mistype a specific subdomain.parkeddomain.com (where they meant to type subdomain.maindomain.com) is in fact, not possible. Very surprising to me indeed, but I learnt something of value. Thank you all those that looked in on this.

Apache Content Negotiation, File Extensions, and Permanent Redirects

Given an Apache 2.x web server that uses Content Negotiation (+MultiViews) to access URLs without their extensions (e.g., allow /foo vs. /foo.php or /foo.html), how does one issue a 301 permanent redirect when someone does in fact try to use those extensions?
The goal is for all roads to lead to the sans extension version of the URL, so /foo/ goes to /foo, and /foo.html goes to /foo. It's the latter one that is proving tricky. (Use case: There are scattered legacy URLs out on the internets that still use the extension. We want those to be permanently redirected.)
There is the canonical link element but, even in the accompanying slides, the suggestion is it's better to do the redirect server-side in the first place.
I've been trying this with mod_rewrite, but it seems like Apache "beats me to it" as it were. It's as if the extension is simply ignored. "No need, I've got it covered" says Apache. But then you can't handle the permanent redirect, and thus extension and no-extension variants are both allowed. Not the desired result. :)
Here's one example. Given a 2-4 character filename consisting of lower-case letters, and a test file placed in /foo/file.html, we want to permanently redirect to /foo/file:
Options +MultiViews
RewriteEngine on
...
RewriteRule ^foo/([a-z]{2,4}).html/$ /foo/$1 [R=301,L]
/foo/file/ and /foo/file.html/ do redirect to /foo/file, but of course /foo/file.html does not. If we try a rule like the following (note the lack of a trailing slash before $):
RewriteRule ^foo/([a-z]{2,4}).html$ /foo/$1 [R=301,L]
... we end up with too many redirects because Apache acts as if the rule is the following, and so it ends up chasing its own tail:
RewriteRule ^foo/([a-z]{2,4})$ /foo/$1 [R=301,L]
In an attempt to be too clever for my own good, I also tried nested parentheses:
RewriteRule ^foo/(([a-z]{2,4}).html)$ /foo/$2 [R=301,L]
No dice. Redirect loop city.
What would be really good is to capture this sort of thing "en masse" so I don't have all these special cases floating around in htaccess.
Another SO question began to address this for the single case of handling html files, but the proposed solution ostensibly requires disabling of Content Negotiation, which isn't good if you still want to use it for images and other file extensions (as it is in my case).
Extra credit: We also want to avoid trailing slashes, so if someone tries /foo/ (which could itself be a .html or .php file) it goes to /foo no matter what. The first rule (above) accomplishes this, but I think it's due to +MultiViews. I have my doubts about using DirectorySlash here, as there may be some risk there that makes it not as worthwhile.

Apache mod_rewrite not doing anything (?)

I'm having some trouble with Apache's mod_rewrite. One of the things I'm trying to get it to do is hide some of my implementation details, so that, for example, the user sees the URL http://www.mysite.com/login but Apache responds with the page at http://www.mysite.com/doc_root/login.php instead (preferably without showing the user that it's a PHP file or the directory structure). Here's what I have in my .htaccess file:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?mysite.com*
RewriteRule ^/(\w+) /doc_root/$1.php [L]
#Redirect http://www.mysite.com to the login page
RewriteRule ^/?$ https://www.mysite.com/doc_root/login.php
But when I go to http://www.mysite.com/login, I get a 404 error even though the page exists. I clearly don't have a great understanding of how the mod_rewrite conditionals and rules work, so can anyone please tell me what I'm doing wrong? Thanks.
Take doc_root out of all the stuff you have it in. That will give you the result you're asking for. However I'm not sure if it's desired or not. How are you going to force someone to login if they manually type http://www.mysite.com/index.php?
Also if you're trying to force all traffic to SSL it's better to use a second VirtualHost and Redirect instead of mod_rewrite. Those are all questions probably better suited for ServerFault
Unless your site has a bunch of different domain names, and you only want mysite.com to do the rewriting, you don't need the RewriteCond. (Potential problem. Apache likes to dick around with the domain name unless you set UseCanonicalName off. If the name isn't what it's expecting, the rewrite won't happen.)
In RewriteCond (and RewriteRule) patterns, . matches any character. Add a backslash before them. (Minor bug. Shouldn't cause rewrites to fail, but they would match stuff like "mysite-com" as well.)
mod_rewrite is actually a URL-to-filename filter. Though it is often used to rewrite URLs to other URLs, sometimes it will misbehave if what you're rewriting to is a URL and it can't tell. (Especially if what it's rewriting to would be an alias, or would otherwise not translate directly to a real filename.) If you add a [PT] flag onto your rule, though, it will consider the rewritten thing a URL and pass it along to the other filters (including the ones that turn URLs into filenames).
Do you really need "/doc_root"? The document root should already be set up in Apache using the DocumentRoot directive, and shouldn't need to be part of the URL unless you have multiple apps on the same domain (in which case it's the app root; the document root doesn't change).
UPDATE:
Another thing i just thought about: Rewrite rules work differently in .htaccess files. Apache likes to strip off the leading slash. So you will probably want to get rid of the first slash in your patterns, or at least make it optional (^/?login instead of ^/login).
^/?(\w+) will match /doc_root/login.php, and cause a rewrite to /doc_root/doc_root.php. You should probably have a $ at the end of your pattern.

URL rewriting with mod_rewrite to provide RESTful URLs

The web server is Apache. I want to rewrite URL so a user won't know the actual directory. For example:
The original URL:
www.mydomainname.com/en/piecework/piecework.php?piecework_id=11
Expected URL:
piecework.mydomainname.com/en/11
I added the following statements in .htaccess:
RewriteCond %{HTTP_HOST} ^(?!www)([^.]+)\.mydomainname\.com$ [NC]
RewriteRule ^(w+)/(\d+)$ /$1/%1/%1.php?%1_id=$2 [L]
Of course I replaced mydomainname with my domain name.
.htaccess is placed in the site root, but when I access piecework.mydomainname.com/en/11, I got "Object not found".(Of course I replaced mydomainname with my domain name.)
I added the following statements in .htaccess:
RewriteRule ^/(.*)/en/piecework/(.*)piecework_id=([0-9]+)(.*) piecework.mydomainname.com/en/$3
Of course I replaced mydomainname with my domain name.
.htaccess is placed in the site root, but when I access piecework.mydomainname.com/en/11, I got "Object not found".(Of course I replaced mydomainname with my domain name.)
What's wrong?
Try using RewriteLog in your vhost or server-conf in order to check the rewriting process. Right now you just seem to guess what mod_rewrite does.
By using RewriteLogLevel you can modify the extend of the logging. For starters I'd recommend level 5.
PS: Don't forget to reload/restart the server after modifying the config.
Here's a quick overview of what's happening:
RewriteCond %{HTTP_HOST} ^(?!www)([^.]+)\.mydomainname\.com$ [NC]
First, the question mark is supposed to be at the end.
$1 would (should) match anything that is not 'www' 0 or 1 times.
$2 matches anything that is not a character 1 or more times, which theoretically would match a blank space there but likely would never match anything.
Then it requires '.mydomainname.com' after those two groupings.
Your first two conditions are looking for two separate groupings.
I'm not sure exactly how you're trying to set up your structure, but here is how I would write it based on your original and expected URL's:
RewriteCond %{HTTP_HOST} !^www\.mydomainname\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(\w+)\.mydomainname\.com$ [NC]
RewriteRule ^(\w+)/(\d+)$ /$1/%1/%1.php?%1_id=$2 [L]
Basically, your first condition is to make sure it's not the URL beginning with 'www' (it's easier to just make it a separate rule). The second condition makes it check any word that could possibly be in front of your domain name. Then your rewrite rule will redirect it appropriately.
Get rid of the last .htaccess line there in your question...
Someone please correct me if I typed something wrong. I don't remember if you have to have the '\' in front of '\w' and '\d' but I included them anyways.
You are doing it backwards. The idea is that you will give people the friendly address, and the re-write rule will point requests to this friendly, non-existent page to the real page without them seeing it. So right now you have it only handling what to do when they go to the ugly URL, but you are putting in the friendly URL. since no rule exists for when people put the friendly URL directly, apache looks for it and says "Object not Found"
So add a line:
RewriteRule piecework.mydomainname.com/en/(*.) ^/$3/en/piecework/$3?piecework_id=([0-9]+)(.*)
Sorry, that's quite right, but the basic idea is, if they put in the URL you like, Apache is ready to redirect to the real page without the browser seeing it.
Update
I'm way to sleepy to do regex correctly, so I had just tried my best to move your example around, sorry. I would try something more simple first just to get the basic concept down first. Try this:
RewriteRule www.mydomainname.com/en/piecework/piecework\.php\?piecework_id\=11 piecework.mydomainname.com/en/11
At the very least, it will be easier to see what isn't working if you get errors.