.htaccess redirect to subfolder, and remove it's name - .htaccess

I'm kind of noob in the world of web so my apologies... I tried many things found on SO and elsewhere, but I didn't manage to do what I want. And the Apache documentation is... well too much complete.
Basically what I want to do is redirect my domain to a subfolder. I found easy solutions for this (many different actually).
http://www.foo.com/
http://foo.com/
should redirect to /bar and appear as http://foo.com/
Using the following I got the expected result :
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^www\.foo.com$
RewriteRule ^/?$ "http\:\/\/foo.com" [R=301,L]
RewriteRule ^((?!bar/).*)$ bar/$1 [NC,L]
But I also want the subfolder as well as filenames not to appear when explicitly entered, i.e :
http://www.foo.com/index.html
http://foo.com/index.html
http://wwww.foo.com/bar
http://foo.com/bar
http://wwww.foo.com/bar/index.html
http://foo.com/bar/index.html
Should all appear as
http://foo.com/
Is this possible ?
Obviously using .htaccess, since I'm on a virtual host.
Thanks

As Felipe says, it's not really possible, because you lose information when you do that R=301 redirect: a hard redirect like this starts a whole new request, with no memory of the previous request.
Of course, there are ways to do similar things. The easiest is to put the original request in the query string (here's a good rundown on how mod_rewrite works with query strings). Sure, the query string does show up in the URL, but most modern browsers hide the query string in the address bar, so if your goal is aesthethics, then this method would be workable.
If you really don't want to show any of the original query in the URL, you might use cookies by employing the CO flag (here are some very good examples about cookie manipulation). At any rate, the information about the original request must somehow be passed in the hard redirect.
But anyhow, and most importantly, why would you want to do something like this? It's bound to confuse humans and robots alike. Great many pages behaved like this back when frames were fashionable, and it was pretty terrible (no bookmarking, no easy linking to content, Google results with the snippet "your browser cannot handle frames", no reloading, erratic back button, oh boy, those were the days).
Speaking of which, if your content is html, you may just use a plain old iframe to achieve the effect (but I'd sincerely advise against it).

Related

htaccess - make url path act as query string

absolute noob here. I have dynamic website with the following query string:
https://example.com/?color=blue
My goal is to mask and convert this query string after ?color= into a path based on the parameter like so:
https://example.com/blue
So if I type into browser https://example.com/blue then content of https://example.com/?color=blue will be displayed while URL remains https://example.com/blue
I am not looking for redirect. I think I need internal rewrite but I am not really sure if this is correct term.
I already tried many solutions from stackoverflow and I spent hours on google but none of those solutions fits my site as I don't have any index.php file which everyone is using in htaccess file.
Sounds pretty straight forward:
RewriteEngine on
RewriteRule ^/?(\w+)$ /?color=$1 [END]
Or something like that:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^/?(\w+)$ /?color=$1 [L]
However since you write that you "tried many solutions" (which you did not share with us) and "spent hours on google" (instead of looking into the documentation of the tool you use) but that still "none of those solutions fits your site" (which you told us nothing about) I have to assume that your actual issue is something else. I cannot answer to that however, since you did not tell us what your actual issue is ...
(note: i am not trying to mock you here, I only try to point out why it is impossible to give a better answer to your vague question ...)
One specific question: if your site does not have an index.php router (or something similar), then how should the final, rewritten URL /?color=blue get processed?

htaccess redirect pretty URLs to ugly ones

So, I'm trying to make my URL's a bit more pretty and sharable. I have a website with some items that users can currently access with example.com/?i=itemName. However, I'd like users to be able to write example.com/itemName instead.
This means I'd have to do some redirection with htaccess. I want to redirect all URL's to example.com itself, but keep the URL the same. To clarify, an example:
User types example.com/niceItem. The server shows the content of example.com, but keeps the URL as example.com/niceItem (alternatively, it can change the URL to example.com/?i=niceItem, then I can simply read the URL with javascript and change it back to example.com/niceItem in the adress bar).
So far, this is the best I could do:
RewriteRule ^/([^\/]+)$ /index.php?i=$1 [NC,L]
The idea is to capture the requests that don't have slashes after the first one (like example.com/niceItem), and then read the file at example.com/index.php?i=niceItem. The problem is, when I load a page like example.com/niceItem, the page displays what the value of i is with php; it should be niceItem, as the link is supposed to be example.com/?i=niceItem, but the value of i is actually the string index.php. Not quite what I wanted. Also, I'd expect the following to work
RewriteRule ^/([^\/]+)$ /?i=$1 [NC,L]
but this actually causes an internal server error.
So, the question is, why do those not work, and how would I be able to achieve what I'm trying to achieve?
PS. Actually, this website I'm talking about is a subdomain of example.com. So, I have sub.example.com which maps to example.com/sub/, and I need the URL's to be prettyfied like sub.example.com/itemName or example.com/sub/itemName. As I mentioned, the format of the URL isn't that big of a deal as long as the itemName part is in there. I'll be able to read the URL with javascript and change it to whatever I want once the page has loaded.
Use RewriteCond
If i is the only query argument that will be passed then
RewriteCond "%{QUERY_STRING}" "(\?i=)(.*)$"
RewriteRule "(.*)/?$" "$1/%2"
If you need to extract i only but keep other query args
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))i=([^&]*)&?(.*)&?$"
RewriteRule "(.*)/?$" "$1/%2?%1%3"
Most every framework provides this sort functionality. It is best not to reinvent the wheel when possible. This is a fragile setup, and it will probably cause you headaches in the future.

htaccess redirect not working for long url

How do I redirect the following long link:
http://www.vbpmonitor.com/index.php?option=com_content&view=article&id=24&utm_source=MagnetMail&utm_medium=email&utm_term=asmith#panaceainc.com&utm_content=EVVWP040716&utm_campaign=White%20Paper%3A%20Optimizing%20VBM%20Quality%20Tiering%20for%20Physicians
to
http://www.vbpmonitor.com/optimizing-vbm-quality-tiering-for-physicians
Redirect 301 /index.php?option=com_content&view=article&id=24&utm_source=MagnetMail&utm_medium=email&utm_term=asmith#panaceainc.com&utm_content=EVVWP040716&utm_campaign=White%20Paper%3A%20Optimizing%20VBM%20Quality%20Tiering%20for%20Physicians http://www.vbpmonitor.com/optimizing-vbm-quality-tiering-for-physicians
As said above in the comments I suspect that you have a glitch in your logic here and that in reality you want to redirection to work the other way 'round. Redirecting from the long to the search engine friendly URL simply does not make any sense. So:
Using a Redirect rule you could try that instead:
Redirect 301 /optimizing-vbm-quality-tiering-for-physicians /index.php?option=com_content&view=article&id=24&utm_source=MagnetMail&utm_medium=email&utm_term=asmith#panaceainc.com&utm_content=EVVWP040716&utm_campaign=White%20Paper%3A%20Optimizing%20VBM%20Quality%20Tiering%20for%20Physicians
This will redirect an incoming request to the short URL to the actually existing long URL. That is the usual scenario.
If however you really want to redirect that short URL to the long version, then you cannot do that with a Redirect rule. This might for example be the case if you accidentally sent out that long URL and have a working redirection setup for the short version. Unfortunately you do not explain anything about that in your question or comments, so I can only guess here.
You'd have to use the more flexible rewriting module and use a combination of RewriteCond and RewriteRule. That allows to "cut out" specific patterns of request URLs and to "redesign" how the request should look like after the rewriting.
This would be a simple example that applies two conditions to rewriting the request for file index.php to the long URL:
RewriteEngine on
RewriteCond %{QUERY_STRING} view=article
RewriteCond %{QUERY_STRING} id=24
RewriteRule ^/?index\.php$ /optimizing-vbm-quality-tiering-for-physicians [L,R=301]
Note: this version should work both in the http servers host configuration and also in those .htaccess style files. Where you always should prefer the first option if you have access.
As said above, I can only guess here with the sparse information you provided. I picked two out of many request arguments, since those appear to be the ones best suited as distinct identifiers. But you may have to tweak things. Note that per default RewriteConds are combined by a logical AND, so they both have to resolve to something truish.
For more precise details about this stuff I would like to point you to the official documentation of those modules again. The documentation is extremely precise, well written and comes with good examples. I would always prefer the information there to snippets you find somewhere in the internet or partial answers to questions...
http://httpd.apache.org/docs/current/mod/mod_alias.html#redirect
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

HTAccess Redirect using main parameter, ignore all others

firstly I know and understand how to redirect based on parameters :)
My issue is that I need to redirect all links based on the supplied MenuID parameter and ignore any other information in the query string, as not all parameters are used in each web page request, e.g. menuid=2738421; is New Products
http://www.domain.com/shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products& limit=5&page=24
or,
http://www.domain.com/shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products&limit=20&page=3
or,
http://www.domain.com/shop.php?menuid=2738421&menuref=Ja&page=12&limit=15
to
http://www.domain.com/new.html?page=x&limit=x
The reason for the redirection is that search-engines have indexed these pages and so I need to prettify the URLs.
Is this actually possible to create a fuzzy redirect criteria?
## 301 Redirects
# 301 Redirect 1 - works for this explicit URL, but need a partial result
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^new\.html$ http://www.monarchycatering.com/shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products&limit=5&page=24 [R=301,NE,NC,L]
Any help gratefully taken, thank you in advance
Mark.
Sorry for the delay, but StackOverflow doesn't seem to have a way to flag answers that have been replied to and need my attention.
OK, if I understand you correctly, you have an incoming "reduced" semi-SEF URL out in the real world (produced by your links), such as
http://www.domain.com/new.html&limit=5&page=24
("real" SEF would be something like http://www.domain.com/new/limit/5/page/24.html)
and you need to use .htaccess to map it to real files and more Query String information:
http://www.domain.com/shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products&limit=5&page=24
You want to detect new.html for example, and replace it by a fixed string shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products&, using the [QSA] flag to append the existing Query String on to the end?
RewriteEngine On
RewriteRule ^new\.html /shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products [QSA]
RewriteRule ^sale\.html /shop.php?menuid=32424&menuref=Ja&menutitle=Products+On+Sale [QSA]
...etc...
I believe that a & will be stuck on the end of the rewritten address if the user supplied a non-empty Query String, but be sure to test it both ways.
P.S. It probably would have been cleaner to use "comment" to reply to my question, rather than adding another answer.
It's not clear to me what your starting point is and where you're trying to end up. Do you have "pretty" URLs that you want to convert into "non-pretty" Query Strings that your scripts can actually digest?
The reason for the redirection is that search-engines have indexed
these pages and so I need to prettify the URLs.
If the search engines have already indexed the Query String non-pretty version, they'll have to now re-index with pretty URLs. Ditto for all your customers' bookmarks.
If you want to generate "pretty" links within your site, and decode them (in .htaccess) upon re-entry to non-pretty Query Strings, that should work. Your customers' existing bookmarks should even continue to work, while the search engines will replace the non-pretty with the pretty URLs.
and thanks for the interest in my question...
I have rewritten parts of my website and Google still has references to the old MenuID parameter and shop.php configuration, but now I rewriten the Query to a prettier format, e.g.
http://www.domain.com/shop.php?menuid=2738421&menuref=Ja&menutitle=New+Products&limit=5&page=24
is now
http://www.domain.com/new.html&limit=5&page=24
The pages represent product categories, and so needed to be displayed in a more meaningful manner. Customer bookmarking is not an issue, as long as I can redirect the pages.
I hope that makes sense, best wishes,
Mark.

Having huge redirect list in .htaccess a Problem?

I want to redirect every post 301 redirect, but I have over 3000 posts.
If I list
Redirect permanent /blog/2010/07/post.html http://new.blog.com/2010/07/23/post/
Redirect permanent /blog/2010/07/post1.html http://new.blog.com/2010/07/24/post1/
Redirect permanent /blog/2010/07/post2.html http://new.blog.com/2010/07/25/post2/
Redirect permanent /blog/2010/07/post3.html http://new.blog.com/2010/07/26/post3/
Redirect per......
for over 3000 url redirect command in .htaccess would this eat my server resource or cause some problem? Im not sure how .htaccess work but if the server is looking at these lists each time user requests for page, I would guess it will be a resource hog.
I can't use RedirectMatch because I added date variable in my new url. Do you have any other suggestions redirecting these posts? Or am I just fine?
Thanks!
I am not an Apache expert, so I cannot speak to whether or not having 3,000 redirects in .htaccess is a problem (though my gut tells me it probably is a bad idea). However, as a simpler solution to your problem, why not use mod_rewrite to do your redirects?
RewriteRule ^/blog/(.+)/(.+)/(.+).html$ http://new.blog.com/$1/$2/$3/ [R=permanent]
This uses a regex to match old URLs and rewrite them to new ones. The [R=permanent] instructs mod_rewrite to issue a 301 with the new URL instead of silently rewriting the request internally.
In your example, it looks like you've added the day of the post to the URL, which does not exist in the old URL. Since you obviously cannot use a regexp to divine the day an arbitrary post was made, this method may not work for you. If you can drop the day from the URL, then you're good to go.
Edit: The first time I read your question, I missed the last paragraph. ("I can't use RedirectMatch because I added date variable in my new url.") In this case, you can use mod_rewrite's RewriteMap to lookup the day component of a post.
You have two options:
Use a hashmap to perform fast lookups in a static file. This means all your old URLs will work, but any new posts cannot be accessed using the old URL scheme.
Use a script to grab the day.
In option one, create a file called posts.txt and put:
/yyyy/mm/pppp dd
...for each post where yyyy is the year of the post, mm is the month, and pppp is the post name (without the .html).
When you're done, run:
$ httxt2dbm -i posts.txt -o posts.map
Then we add to to the server/virtual server config: (Note the path is a filesystem path, not a URL.)
RewriteMap postday dbm:/path/to/file/posts.map
RewriteRule ^/blog/(.+)/(.+)/(.+).html$ http://new.blog.com/$1/$2/${postday:$1/$2/$3}/$3/ [R=permanent]
In option two, use pgm:/path/to/script/lookup.whatever as your RewriteMap. See the mod_rewrite documentation for more info about using a script.
Doing the lookup in mod_rewrite is better than just redirecting to a script which looks up the date and then redirects to the final destination because you should never redirect more than once. Issuing a 301 or 302 incurs a round trip cost, which increases the latency of your page load time.
If you have some way in code to determine the day of a post, you can generate the rewrite on the fly. You can setup a mod_rewrite pattern, something like .html and set up a front controller pattern to calculate the new url from the old and issue the 301 header.
With php as an example:
$_SERVER['REQUEST_URI']
will contain the requested url and
header("Location: http://new.blog.com/$y/$m/$d/$title/",TRUE,301);
will send a redirect.
That's... a lot of redirects. But the first thing I would tell you, and probably the only thing I can tell you without qualification, is that you should run some tests and see what the access times for your blog are like, and also look at the server's CPU and memory usage while you're doing it. If they're fairly low even with that giant list of redirects, you're okay as long as your blog doesn't experience a sudden increase in traffic. (I strongly suspect the 3000 rewrites will be slowing Apache down a lot, though)
That being said, I would second josh's suggestion of replacing the redirects with something dynamic. Like animuson said, if you're willing to drop the day from the URL, it'll be easy to set up a RewriteRule directive to handle the redirection. Otherwise, you could do it with a PHP script, or generally some code in whatever scripting language you (can) use. If you're using one of the popular blog engines, it probably contains code to do this already. Basically you could do something like
RewriteRule .* /blog/index.php
and just let the PHP script sort out which post was requested. It has access to the database so it'll be able to do that, and then you can either display the post directly from the PHP script, or to recover your original redirection behavior, you can send a Location header with the correct URL.
An alternative would be to use RewriteMap, which lets you write a RewriteRule where the target is determined by a program or file of your choice instead of being directly specified in the configuration file. As one option, you can specify a text file that contains the old and new URLs, and Apache will handle searching the file for the appropriate line for any given request. Read the documentation (linked above) for the full details. I will mention that this isn't used very often, and I'm not sure how much faster it would be compared to just having 3000 redirects.
Last tip: Apache can be significantly faster if you're able to move the configuration directives (like Redirect) into the server or virtual host configuration file, and disable reading of .htaccess entirely. I would guess that moving 3000 directives from .htaccess into the virtual host configuration could make your server considerably faster. But even moving the directives into the vhost config file probably wouldn't produce as much of a speedup as using a single RewriteRule.
It's never a good idea to make a massive list of Redirects. A better programming technique is to simply redirect the pages without that date variable then have a small PHP snippet that detects if it's missing and redirects to the URL with it included. The long list looks tacky and slows down Apache because it's checking that URL (any every other URL that might not even be affected by this) against each line. If it were only 5 or so, I'd say fine, but 3,000 is a definite NO.
Although I'm not a big fan of this method, a better choice would be to redirect all those URLs normally using a single match statement, redirecting them to the page without the date part, or with a dash or something, then include a small PHP snippet to check if the date is valid and if not, rewrite the path again to the correctly formed URL.
Honestly, if you didn't have that part there before, you don't need it now, and it will probably just confuse the search engines changing the URL for 3,000 posts. You don't really need a date in the URL, a good title is much more meaningful not only to users, but also to search engines, than a bunch of numbers.

Resources