Create Apache mod rewrite rule to process all request to subdirectory - apache

I want to redirect all incoming requests to a subdirectory, but can't figure out how. I looked here but that did not work for me.
So, if someone visits www.example.com/test, I want it to redirect to: www.example.com/test/subdirectory, but the URL still needs to be www.example.com/test
I also need the parameters to work, for example www.example.com/test/index.php?action=home must redirect to www.example.com/test/subdirectory/index.php?action=home.
I hope someone can help me!

So in fact what you ask for is not a redirect.
A redirect means the web server will send a new url containing the subdirectory, the browser will then request this new url, and show it in the url bar of the browser.
What you want is to tranparently map an directory structure to a real directory structure which differs. This is what Apache can do easily with the Alias instruction. Mod-rewrite could also do that, with RewriteRules not containing the [R] tag, this would imply an internal rewrite, not a redirect HTTP response. A [QSA] tag would also tell mod-rewrite to keep the current query string parameters on the rewritten url. But Mod-rewrite is not always simple to understand, and your problem is simple enough for a basic Alias, which is almost always included in Apache (more often than mod-rewrite).
this should be ok:
Alias /test /test/subdirectory

Try adding the following to the .htaccess file in the root directory of your site.
Query string parameters are passed through by default.
RewriteEngine on
RewriteBase /
#if not an existing file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# rewrite to subdirectory
RewriteRule ^(.*)(/[^/]+)?$ /$1/subdirectory/$2 [L,QSA]

Related

htaccess Remove directory from end of URL in apache

Ok, so I know this is a question that has been asked many times, however, I have not been able to find an answer to my particular case, so please do not shoot me down.
I have a website: http://gmcomputers.co.za.
I am redirecting this URL, using .htaccess file, to a subfolder to load the content:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/$
RewriteRule (.*) /gmcomputers/ [L,DPI,R=301]
Which works perefectly, except when I go to http://gmcomputers.co.za I get http://gmcomputers.co.za/gmcomputers/.
So my question is, how do I modify the above code to remove the /gmcomputers/ from being appended?
Please note I copied the code above from a website as I am not at all experienced in redirect, etc and am still learning. Also, the reason I am using .htaccess to redirect is due to there being other websites in the root directory and I therefore cannot edit any config files for Apache.
Thanking you.
You contradict yourself in your question. On the one hand you write that you want to redirect and that this "works perfectly", but then you write that you do not want that result.
My guess is that you actually do not want to redirect at all, but that instead you want to internally rewrite your requests to point to that server side folder. While the URL visible in the browser's URL bar does not show that folder. Is that what you are trying to ask?
If so take a look at this example:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/gmcomputers
RewriteRule ^ /gmcomputers%{REQUEST_URI} [END]
You might want to add an actual redirection to direct clients actually using the folder name in their requests:
RewriteEngine on
RewriteRule ^/?gmcomputers/(.*)$ /$1 [R=301,END]
RewriteCond %{REQUEST_URI} !^/gmcomputers
RewriteRule ^ /gmcomputers%{REQUEST_URI} [END]
Best is to implement such rules in the central http server's host configuration. If you do not have access to that you can instead use a distributed configuration file (typically called ".htaccess") located in the DOCUMENT_ROOT folder configured for the http host, if you enabled the consideration of such files in your host configuration . Though that comes with a number of disadvantages. Above implementation works likewise for both approaches.

Why is this RewriteRule altering QUERY_STRING, but leaving REQUEST_URI untouched?

I have a copy of Concrete5, a PHP-based CMS, running on example.com.
Concrete5 comes with the following basic instructions for pretty URLs (redirecting all URLs to a central index.php)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/c5.7
RewriteRule ^.*$ c5.7/$0 [L] # Concrete5 is running in the c5.7/ subdirectory
</IfModule>
Pretty straightforward.
Now I have a certain set of URLs that take the form
/product/{productname}
that I need to forward to the Concrete5 (virtual) URL
/products/details?name={productname}
That URL is set up and works as expected when I enter it manually in the browser.
So I added a line to the htaccess file and it now looks like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# New rule for products
RewriteCond %{REQUEST_URI} ^/product/
RewriteRule ^product/(.+)$ /products/details?name=$1 [QSA]
RewriteCond %{REQUEST_URI} !^/c5.7
RewriteRule ^.*$ c5.7/$0 [L]
</IfModule>
I can confirm the RewriteRule gets triggered when I choose a random, external URL as the redirection target.
But whenever it is an internal redirect like above, what happens is, I get a 404 inside Concrete5. When I inspect what was passed to it, I see:
REQUEST_URI: /product/my-random-product
QUERY_STRING: name=my-random-product
So it appears that the rule is triggered and does some rewriting, but REQUEST_URI remains unchanged!
Why?
Is it because PHP 7.1 is running via CGI?
I have tried a zillion variations and all the flags in the book, with little success.
The REQUEST_URI in PHP is not the same as the REQUEST_URI within mod_rewrite, so you can't do it like this. In PHP it always contains the original URL. So you can't change it like this if your CMS is working off that.
You should set up your CMS to use the URLs you want, rather than trying to augment your CMS's URL rewriting like this.
If you inspect REDIRECT_URL in PHP you will see the last rewritten URI.
REQUEST_URI in PHP will always be the original request URI.
Because this is already explained by LSerni and SuperDuperApps, I won't elaborate.
Instead, I'm offering a quick solution: modify the REQUEST_URI and add a name parameter in PHP instead of in .htaccess.
Add the following code to the start of your Concrete5 index.php to make sure that REQUEST_URI is modified
before any Concrete5 code runs:
if(preg_match('-^/product/([^?]*)-',$_SERVER['REQUEST_URI'],$matches)){
$_SERVER['REQUEST_URI'] = '/products/details';
$_GET['name'] = $matches[1];
}
Your setup works on a PHP 7.1 machine (without Concrete5). It does call a script I just put in, which is in /c5.7/products/details. So the Apache part is working.
Inside the script, I see that REQUEST_URI is the old value prior to the rewrite.
So its value is normal and it not being rewritten is a red herring - it isn't supposed to be rewritten. The 404 error must be due to something else.
Your Concrete5 routing should support the real URL, not just the virtual one, because C5's routing relies itself on REQUEST_URI. If this is so, you need to create a route for your short URLs
Route::register('/product/{productname}' ...)
and an appropriate controller to get the parameters and invoke the "old" controller.
One possibility using .htaccess could be this, but I'm not too sure it will work since REQUEST_URI is still left unchanged:
# New rule for products
RewriteCond %{REQUEST_URI} ^/product/
RewriteRule ^product/(.+)$ c5.7/products/details?name=$1 [L,QSA]
Otherwise you need to do an external redirect, which will disclose the URL in the browser:
RewriteRule product/(.*)$ http://.../products/details?name=$1 [QSA]
See also this other question.

Apache httpd.conf rewrite rules

I have some rewrite rules in my httpd.conf file. Is there a way to get apache to check the rewrite rules only if the url is not valid? My rewrite rules are preceded by checks for the REQUEST_FILENAME being a valid file, and a valid folder. But the documentation mentions that the rewrite conditions are checked only AFTER it finds a match for the rewrite rule.
So, whenever there is a request for a URL, apache checks each rewrite rule for that URL. Almost all the pages have images, .js and .css files and a few more files with them. Apache checks those too, against the rewrite rules in the httpd.conf (I see this in the RewriteLog generated for each URL). This significantly slows down the site.
I am aware of the FallbackResource directive. I don't want to use it as of now, because it returns a http status code of 200 by default. I want to return the correct status code (usually a 301) whenever there is a request for a page that was not found by Apache (usually, the incorrect URL has a correct counterpart, hence the need to send a 301). Sending the correct http status code also benefits our seo efforts. If there is a way to send the correct http status code using the FallbackResource directive, I would be open to using that option.
I have tried googling for these issues, and didn't find an answer. I have tried with different RewriteCond (s) but, like the documentation says, each rewriterule is checked anyways.
Any pointers on this would be of much help.
It does appear that there'd be some readings to do for you but, I always use this as "bible" when it comes to rewrite rule and haven't ceased to failed me. Perhaps this would do the same for you.
http://corz.org/server/tricks/htaccess2.php
Why not use the following:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /not-found.php [L]
I would put in a .htaccess file located in the root folder. That way you can easily customize it for each site.

Apache HTACCESS routing with Codeigniter under what appears to be a root level folder

I have an interesting issue that I can't seem to get through. We have a URL that has been setup to route all requests to that URL (via nginx on another server) to my Codeigniter app (that exists on another server). For example, the URL is like this:
http://www.site.com/myappname/controller/function/parameter
Under normal conditions in Codeigniter, it routes the first element after the trailing forward slash to a controller class, then the second to a function within the class, and the third/etc as paramaters of that function.
What I need it to do is to disregard the "myappname" in the URL and have it send through the URL without that. The "myappname" is NOT a folder on the server.
I'm not 100% sure if I need to add new HTACCESS rules, or if I can do this programmatically through Codeigniter.
My current HTACCESS file:
RewriteEngine on
RewriteCond $1 !^(index\.php|sitemap\.xml|robots\.txt|public|favicon\.ico)
RewriteRule ^(.*)$ /index.php/$1 [L]
This is a basic, and straight forward HTACCESS setup for all Codeigniter apps, however, using this, and using the structure above, if I go to, http://www.site.com/myappname, with "http://www.site.com/myappname" set as my base_url in the Codeigniter config, Codeigniter then translates it as:
http://www.site.com/myappname/myappname
So...can anyone help? I also tried to add the following code to the top of my config/routes.php file:
$_SERVER['REQUEST_URI'] = str_ireplace('/verified', '', $_SERVER['REQUEST_URI']);
That actually works partially, but now when I request CSS/JS files, from the root, it doesn't pull those in correctly because I use the built in site_url() function to build dynamic links based on the site's "base_url" property. I don't think I can do this 100% programmatically inside Codeigniter (through overwriting system level functions) because my CSS/JS/etc exist in a /public folder in the root of my app (that's obviously excluded from routing via my RewriteCond).
Anyone have a suggestion?
Try adding a RewriteBase to your htaccess:
RewriteEngine On
RewriteBase /myappname/
RewriteCond $1 !^(index\.php|sitemap\.xml|robots\.txt|public|favicon\.ico)
RewriteRule ^(.*)$ /index.php/$1 [L]

Apache Rewrite: directory tree to subdomain directory

I have a web application that has one set of files used by 50+ clients and all the configuration for each site comes from a config.php file in their respective directories. This is accomplished with PHP parsing the URL. All this works fine, just having an issue with custom uploaded documents the client can do and are located in
/var/www/sites/user1/cache
There can be multiple subdirs. So when requesting
http://user1.site.com/cache/subdir1/image.jpg
it needs to be read from
/var/www/sites/user1/cache/subdir1/image.jpg
The client is allowed to upload any file type, so I just need the rewrite to take any /cache requests, then grab the subdomain and point to proper directory.
Came up with this, but am still getting an invalid page
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([^\.]+)\.site\.com$
RewriteRule ^cache/(.*)$ /sites/%1/cache/$1 [L]
Any help is appreciated.
If I read the RewriteRule documentation correctly, the L flag on its own would generate an internal redirection, meaning that the substitution would be interpreted as a local file system path.
Try using the complete path:
RewriteRule ^cache/(.*)$ /var/www/sites/%1/cache/$1 [L]
or do an external redirection (using HTTP return status "302 MOVED TEMPORARILY"), to let the user's browser re-send the request with the new path:
RewriteRule ^cache/(.*)$ /sites/%1/cache/$1 [L,R]
The /var/www/ is where the files are on the filesystem. I was routing based on the document root so I didn't need to put that there. But I realized I was missing the leading forward slash on the /cache/. Though your answer wasn't really what I was looking for, it made me see what I was missing. Thanks.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([^\.]+)\.site\.com$
RewriteRule ^/cache/(.*)$ /sites/%1/cache/$1 [L]