htaccess forward to subfolder but hide subfolder name - php

I have an issue writing some regex to go inside my htaccess file.
Basically, my site has been setup so that index.php and all other site files are not in the root (public_html) directory but instead are in http://fitnessquiz.co.uk/fitnessquiz.co.uk/
Initially I tried the following in my public_html folder:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^fitnessquiz.co.uk$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www.fitnessquiz.co.uk$
RewriteCond %{REQUEST_URI} !fitnessquiz.co.uk/
RewriteRule (.*) /fitnessquiz.co.uk/$1 [L]
which correctly navigates to my homepage and displays the url correctly but then when I click any link I get a "no input file specified" message. So then I tried replacing with:
RewriteCond %{REQUEST_URI} !^/fitnessquiz.co.uk/
RewriteRule ^(.*)$ /fitnessquiz.co.uk/$1 [L,R=301]
After which the site works but every url looks like this:
http://fitnessquiz.co.uk/fitnessquiz.co.uk/someotherfolder/etc.php
I've tried various htaccess regex solutions listed elsewhere on here but none seem to work, how do I accomplish both of these things i.e. redirect to /fitnessquiz.co.uk for every url but hide the duplicate url name/folder. Im on a shared server so don't have permissions to change any server/apache settings directly.

According to this answer by nuked on a previous post you could try:
RewriteCond %{THE_REQUEST} ^GET\ /fitnessquiz.co.uk/
RewriteCond %{HTTP_HOST} ^(www\.)?fitnessquiz.co.uk$
RewriteRule ^fitnessquiz.co.uk/(.*) /$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^(www\.)?fitnessquiz.co.uk$
RewriteRule !^fitnessquiz.co.uk/ fitnessquiz.co.uk%{REQUEST_URI} [L]
This set of rules worked for me on a very similar situation. I had employed the same cure, (re-direct if calling the folder and hide after re-writing it) but I never got the order right on my own. Thus I kept seeing the page not found errors too. Below is my attempt to explain the actions, for my own learning, hopefully others too.
RewriteCond %{THE_REQUEST} ^GET\ /fitnessquiz.co.uk/
Is asking the question, does THE_REQUEST contain the subfolder you need to hide?
RewriteCond %{HTTP_HOST} ^(www\.)?fitnessquiz.co.uk$
Checks if the request is for the correct host.
RewriteRule ^fitnessquiz.co.uk/(.*) /$1 [L,R=301]
Rewrite the URL as one without the subfolder and call the new link in the redirected browser. Note:
L : Last step. Stop processing other rules
R=301 : After re-writing, redirect the browser to the new URL.
When the page is redirected it has no subfolder so the first RewriteRule is skipped. And then
RewriteCond %{HTTP_HOST} ^(www\.)?fitnessquiz.co.uk$
checks if calling the right host. And then
RewriteRule !^fitnessquiz.co.uk/ fitnessquiz.co.uk%{REQUEST_URI} [L]
rewrites the url that has not the subfolder to use the correct subfolder without redirecting the page, and while hiding actual subfolder from the browser. Again note:
L : Last step. Stop processing other rules

Related

Apache rewrite rule causes "too many redirects" for JS and CSS files

I'm working on a project with a custom CMS (which is written by someone else). There's an existing .htaccess file with some conditions and rewrite rules, one of which directs requests to the index.php file. This file loads the CMS object, and calls a method to check if the URL leads to an existing CMS page. If it doesn't, the user is redirected to a 404 page.
The CMS also allows you to build custom modules on top of the base CMS functionality. Usually this is used for user management and stuff like that, but for this project the client wants to be able to build a knowledge base with hundreds of knowledge base items, which in the CMS would become a giant mess. I've now built a custom module for these items, and they also store a slug. I want the URLs to be /knowledgebase/items/item-slug, but with the existing configuration this would lead to a redirect to the 404 page because, as far as the CMS is aware, the item-slug doesn't lead to an existing CMS page. This is the current rewrite section in the .htaccess file.
# Enable the rewrite engine
RewriteEngine On
RewriteBase /domain.tld
# SSL Redirect 301 transfer the current request.
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# never rewrite for existing files, and links
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
#RewriteCond %{REQUEST_FILENAME} !-d
# For Friendly URLs
RewriteRule ^knowledgebase/items/(.*)$ index.php?knowledge_item_slug=$1 # my own RewriteRule
RewriteRule ^(.*)$ index.php [L]
In index.php I've added the following lines to check if a custom knowledgebase item needs to be shown
if (isset($_GET['knowledge_item_slug']) && $_GET['knowledge_item_slug'] !== '') {
include_once(__DIR__ . '/components/knowledgebase_item.php');
exit(0);
}
This works fine, going to knowledgebase/items/test loads the test item as it should. With this rule added however, CSS and JS files can no longer be found after a hard reload (clearing the cache) and cause net::ERR_TOO_MANY_REDIRECTS errors in the console.
I've modified the rule to RewriteRule ^kennisbank/items/(.*)$ index.php?knowledge_item_slug=$1 [C] (basically just added the [C] flag) and now the item detail page works, but any other page causes the error The requested URL /domain.tld/page was not found on this server.
I've also tried placing RewriteRule ^(.*)$ index.php above my own RewriteRule (without the [L] flag, obviously), but then my own one doesn't work at all.
I'm not too familiar with Apache rewrites, any idea what's causing this issue?
Problem is that you have 2 RewriteRule rules after checking for non-file and non-directory in RewriteCond. Only immediate next RewriteRule is affected by one or more RewriteCond hence last rule executes without any conditions that routes every request including css/js/images to index.php.
You can have your .htaccess as this:
# Enable the rewrite engine
RewriteEngine On
RewriteBase /domain.tld
# SSL Redirect 301 transfer the current request.
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# never rewrite for existing files, and links
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
# For Friendly URLs
RewriteRule ^knowledgebase/items/(.*)$ index.php?knowledge_item_slug=$1 [L,NC,QSA]
RewriteRule ^ index.php [L]
Do-nothing rule RewriteRule ^ - [L] will skip any rules below that line for the conditions above i.e. non-file and non-directory.

.htaccess not excluding sub directory with rules

I'm asking a question regarding my .htaccess. I'll quickly explain what i'm trying to accomplish and how it's not working.
I'm using the $_GET directory as a rule for the page.
i.e https://example.com/test?p=page1 = https://example.com/test/page1
I also have a directory called "account" inside this /test/ directory but when I try to access the page.
https://example.com/test/account it redirects me to https://example.com/test/account/?p=account
note (https://example.com/test/account/ works fine)
I've tried disabling it by following methods on other StackOverflow posts but none of this is working.
My rule is:
RewriteRule ^([0-9a-zA-Z-_\ ]+)/?$ index.php?p=$1 [NC,L]
Is there any way I can configure this rule to exclude the word "account" and "admin" etc I've tried placing a .htaccess with the rewrite engine off but that doesn't work because the .htaccess thinks /account is a page rather than a directory.
I've tried other methods which stop directories with the same issue. It doesn't think /account is a directory. It thinks it's a page.
Any help would be great!
add this line above to exclude requests with account or admin in them
RewriteCond %{REQUEST_URI} !(account|admin)$ [NC]
put that above your current rule and it should exclude using the rule on requests including those terms.
here is what I use (have for ages), to do what you are wanting to do:
**I am pretty sure I could reduce this to a single set of expressions but I'm not that good. Without the second I miss domain.tld and without the first I miss fancy.domain.tld
ErrorDocument 404 http://domain.tld
RewriteEngine On
RewriteCond %{REQUEST_URI} !(actionspage|\/excludeddir\/|\/otherdir\/).*$ [NC]
RewriteCond %{HTTP_HOST} ^(.+)\.domain\.tld$ [NC]
RewriteRule ^(.*)$ index.php?pre=%1&pos=$1 [L,QSA]
RewriteCond %{REQUEST_URI} !(actionspage|\/excludeddir\/|\/otherdir\/).*$ [NC]
RewriteRule ^(.*)$ index.php?pre=0&pos=$1 [L,QSA]

Preety Url: stop loading page with .php extension

I am using pretty url for my project and it is working fine.
http://testurl.com/user/12345
I am using .htaccess for redirection.
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/user\.php\?id=([0-9]+)\s [NC]
RewriteRule ^ user/%1? [R=301,L]
RewriteCond %{THE_REQUEST} \s/user\.php\?id=([0-9]+)&name=([^&\s]+)\s [NC]
RewriteRule ^ user/%1/%2? [R=301,L]
RewriteRule ^user/([0-9]+)/?$ user.php?id=$1 [L]
RewriteRule ^user/([0-9]+)/([^/]+)$ user.php?id=$1&name=$2 [L]
Today i found if i change the link in browser like this http://testurl.com/user.php then page is also loading i want to show error message (Alert) if someone directly trying to access
The best way is to add your error or redirect in the user.php without id query string.
But you also can add (after RewriteBase /):
RewriteCond %{THE_REQUEST} \s/user\.php\s [NC]
RewriteRule ^ - [F]
You might as well solve your problem through code reorganization. I did this in one of my projects, and it has worked well.
1. When you create a pretty URL, move the according file into another directory
So, in this case, you had the URL example.com/user.php?id=123 visible externally. Now, you want a pretty URL for it, e.g. example.com/user/123.
On file level, before you had
- user.php
I suggest you move that to another directory, where all scripts live which are accessed by pretty URL only:
- rewrites/
|- user.php
2. Create redirects for your old URL to your new URL, externally
The same as you did above.
RewriteCond %{THE_REQUEST} \s/user\.php\?id=([0-9]+)\s [NC]
RewriteRule ^ user/%1? [R=301,L]
RewriteCond %{THE_REQUEST} \s/user\.php\?id=([0-9]+)&name=([^&\s]+)\s [NC]
RewriteRule ^ user/%1/%2? [R=301,L]
3. Rewrite the new, pretty URL to moved script, internally
The same as you did above, with difference that the directory name rewrites is added.
RewriteRule ^user/([0-9]+)/?$ rewrites/user.php?id=$1 [L]
RewriteRule ^user/([0-9]+)/([^/]+)$ rewrites/user.php?id=$1&name=$2 [L]
4. example.com/user.php now fails with a 404
Because /user.php does not exist anymore in the file system, it automatically fails with a 404 if called without params.
5. Benefits
This approach might sound like additional work for nothing, but these are the benefits making it worthwile in my opinion:
You do not need an additional .htaccess rule for error handling
You get better code organization
You get better overview of what is already accessible with pretty URL

All my .htaccess redirects are going to index.php

I am trying to redirect all my website traffic from any url to https://, secure ssl using a .htaccess file. This has to match the current domain and redirect including any sub url's.
My code:
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP_HOST} ^shop.test.com$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The issue i am having is that all traffic is being sent to index.php
shop.test.com/testurl
goes to - https://shop.test.com/index.php
expected - https://shop.test.com/testurl
This is most likely due to another rule that writes everything to index.php and uses that as front controller.
Make sure you place above rule as your very first rule just below RewriteEngine On line.

Redirect to another folder

I read this .htaccess rewrite to redirect root URL to subdirectory and i'm trying to achieve the same things.
The solution with most up votes was:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
RewriteRule ^$ store [L]
Now, looking at the comments it seems to be working good.
The problem is that I'd like not to hardcode any path (as instead provided above "www.example.com"). I'd like that my .htaccess inside projectname/ redirects to projectname/public/ despite what the real server host is. So that if I put projectname/ inside the root server of www.pinco.com it redirects to www.pinco.com/projectname/public/ but it shows www.pinco.com/projectname/.
How can I achieve that?
The example you found is actually doing two different things.
# This is actually just redirecting all http://example.com/somepage/
# to http://www.example.com/somepage/, to ensure all URLs have the www.
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
The second rewrite is what will help you achieve what you're trying to do.
# This redirect all requests for http://example.com -> http://example.com/newdir
# If you are looking to redirect the request, so the URL contains directory name,
# you can change the [L] to [R=301,L]
RewriteRule ^$ /newdir [L]
# If your concerned about direct access to a particular page without the sub-dir
# you will want to add something like this
RewriteCond %{REQUEST_URI} !^/newdir
RewriteRule (.*) /newdir$1 [R=301,L]
So, in that case, you won't have to be concerned with domain that the application is running on.
try to add this line, and :
RewriteBase /projectname
And you stay inside the project.

Categories