Having some experience with procedural php I watched some tutorials about OOP and the MVC model (with php). Things start to get more clear and I wanted to put the theory to practice.
The tutorial I'm following works with an app folder and a public folder, both subfolders of the root directory. There's an index.php file in the public folder and a htaccess file that redirects all requests (in the public folder) to none existing files to index php. The code in that file is:
<IfModule mod_rewrite.c>
Options -Multiviews
RewriteEngine On
RewriteBase /public
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
</IfModule>
That works fine.
In the root folder there is also a htaccess file with the purpose of redirecting all url requests to the public folder (in case /public/ is not in the url. The code in that file is:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
</IfModule>
That goes wrong, and it's the second RewriteRule that causes the problems. If I for example browse to
www.mywebsite.com
the browser redirects to www.mywebsite.com/public/index.php
But if I browse to www.mywebssite.com/shop (shop is not an existing file) I suppose the browser redirects to www.mywebsite.com/public/index.php?url='shop', but instead there is an internal server error. It seems to be the second RewriteRule that causes the problem.
What could be the problem?
I am on mobile I haven't tested it but looks like you could be reaching out to maximum redirect limits here why because your condition in your root htaccess isn't looking good to me, try this once.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteCond %{REQUEST_URI} !^/public/? [NC]
RewriteRule (.*) public/$1 [L]
</IfModule>
Issues in OP's approach: You haven't mentioned any condition to when it should redirect so it doesn't know when to stop hence it's creating a loop here IMHO.
Related
I'm using some software that sits in the /var/www/html folder and manages URL redirects through .htaccess (the software isn't Wordpress, but it manages URL redirects in a similar way).
I need to carve two folders (/var/www/html/folder1 and /var/www/html/folder2) out from the redirect rules, which are at the very bottom of the .htaccess file. I read through a ton of documentation but can't seem to make the following work in .htaccess (which sits in /var/www/html):
Options -Indexes
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteBase /
#force HTTPS
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#carve out these folders
RewriteRule ^/folder1($|/) - [L]
RewriteRule ^/folder2($|/) - [L]
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>
When I go to the directories in question (eg. https://example.com/folder1), I get: Forbidden You don't have permission to access /folder1/ on this server.
Any ideas?
I can't comment as I'm new but do the two folders have any sort of index page? Otherwise you will get a 403 response because you have disabled indexes at the top of your file excerpt.
When I attempt to hit my site which is at mydomain.com/subfolder, I get a 404 (from Apache).
/subfolder/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>
/subfolder/webroot/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
To confirm that mod_rewrite works, I added this in the /subfolder/.htaccess file which promptly redirected:
Redirect 301 / http://other-domain-owned.com/
So, .htaccess are live and mod_rewrite works.
On my development environment, I was able to make the site work in the same /subfolder by symply enabling .htaccess files for that folder via a Directory directive.
Some tutorials say to add RewriteBase / but this didn't help.
Instead of RewriteBase, you can also use an absolute path. Additionally, the first two rules can be simplified to one
RewritRule ^(.*)$ /subfolder/webroot/$1 [L]
Similar the second part
RewriteRule ^ /subfolder/webroot/index.php [L]
Finally, Redirect and RewriteRule are from different modules. So, if one of the directives is working, this is no proof for the other one working too.
So I bought a script from the other guy (nothing fancy, let's say just a customized CMS) which is kinda complicated and uses frameworks that I don't know nothing about except names like "bootstrap", "laravel" and so. I am the guy who knows the basis and know some things from intermediate level but again, only some so when I see some fancy solutions I am getting confused.
Like here - I have never seen page built on files with strange extensions and two .htaccess files - one in root, and second in /public/ folder. Still, even though there are so many files, everything works really fine and fast.
Here is the issue's description:
So it seems that when browser loads the page (domain.com), it requests (I guess) content from /public/ folder and everything works fine and domain remains as domain.com. The thing is, that domain.com/public also works and I want to create redirection on this specific address just to prevent indexing this crappy-looking address of domain.com/public but bearing in mind, that domain.com should still work fine.
I have tried maaany solutions found here on SO and on other pages but they resulted in either crashing page (internal server error) or not doing anything at all. I think some of them might work but only when files are not embedded in another sub-folder. Eh I don't know, I am out of ideas. Can you please help me?
Here is the root's .httaccess
RewriteEngine On
RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]
RewriteRule ^((?!public/).*)$ public/$1 [L,NC]
And here is the public/.htaccess
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
It looks to me like what you have should work, specifically the first condition + rule in the root .htaccess is meant to do what you're asking. I would polish it up a little:
In /.htaccess:
RewriteEngine On
RewriteBase /
# Fix URLs that begin with "public" subdirectory
RewriteCond %{THE_REQUEST} \s/public(?:/(\S*))?\s
RewriteRule ^ %1 [NS,NE,R=301,END]
# Internally rewrite everything else
RewriteRule ^(?!public/).* public/$0 [DPI,L]
In /public/.htaccess:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Pretend this is the root
RewriteBase /
# Redirect trailing slashes if not a folder
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [DPI,R=301,END]
# Handle front controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?!index\.php$). index.php [DPI,END]
</IfModule>
You can use L instead of END if your version of Apache is old, you'll know because of a 500 error.
Our web server is structured as follows
/path-to-docdir [Contains main pages]
./app/ [Some application not directly related to the main content]
The main pages are served fine. In the app directory I am trying to use mod_rewrite to redirect all pages to an index.php in a public directory
So a request to
/server/app/start/login/ => /server/app/public/index.php
/server/app/start/login => /server/app/public/index.php
/server/app/start/login?name=someone => /server/app/public/index.php?name=someone
The front controller relies on the last two components of the REQUEST_URI string to interpret controller and action.
To do the above I have created the following .htaccess file in the app directory
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ public/ [L]
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Here, I find that the server goes in a redirect loop for the above URLs. I tried replacing $1 with index.php and that does bring up the page, but the internal references within the page to script files run into errors.
After some searching around, I added the following line:
RewriteBase /app/
And that did not seem to make any difference. I should also note that everything works as expected if I make the app directory as the server root directory.
I've also turned on debug logging and all I could gather from that was that the server was indeed going into a redirect loop.
[perdir /path-to-docdir/app/] internal redirect with /app/public/public/public/public/public/public/public/public/public/public/public/start/login/ [INTERNAL REDIRECT]
I'm not really sure where to start looking at this point, so any help or pointers to move me further would be much appreciated.
Edit:
This htaccess file worked for me - if anyone else is looking for a solution. Apparently, I was missing rewrite conditions
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ public/index.php?$1 [L]
</IfModule>
A few points:
A RewriteBase path does not need a trailing slash, so RewriteBase /app/ should be RewriteBase /app.
RewriteRule ^(.*)$ public/$1 makes RewriteRule ^$ public/ superfluous. The former will match http://yourserver/app and internally rewrite as http://yourserver/app/public, so there's no need for the latter.
Finally, try adding a rewrite condition:
RewriteEngine On
RewriteBase /app
RewriteCond %{REQUEST_URI} !^/app/public/
RewriteRule ^(.*)$ public/$1 [L]
Background information:
I've searched stackoverflow for a specific solution and couldn't find one that fixed my situation. Thanks in advance for any help you can offer. Your knowledge is appreciated.
I've decided to accept a contract to "convert" (in the client's words) a Joomla site into a WordPress site. Everything is going along smoothly, except that the Joomla site links to .html files, both in its navigation and in the content of 100+ posts.
Instead of going through each post one-by-one and updating the links or running a SQL command to remove ".html" from URLs, I've decided to put the pressure on .htaccess, with which I am somewhat comfortable.
What I'm trying to do ↓
In WordPress, I have custom permalinks enabled, and it is as follows:
/%category%/%postname%
Here's an example of what one of the old URLs in the posts looks like:
http://the-site.com/category/the-webpage.html
I need the htaccess file to tell the webserver to remove the .html so the user, after visiting "http://the-site.com/the-webpage.html" is instead sent to:
http://the-site.com/category/the-webpage
I'm setting up the page stubs to follow the file name of the Joomla pages, so http://the-site.com/category/the-webpage will work.
My question:
Can you help me discover the solution to removing .html from the URL when someone visits the site, even if the HTML file doesn't exist on the server?
Here's how the .htaccess file looked before I made changes:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Here's the latest .htaccess file as of 5:35pm Eastern:
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.html$
RewriteRule ^(.*)\.html$ $1 [R=301,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
The ↑latest .htaccess changes work. Thanks Tim!
This will work to force an external redirection to your new URLs, but this may not be ideal for your situation. I'm still trying to think if there's a way to keep the redirection internal and update the variable that WordPress uses to determine which page to serve up, but so far I haven't thought of anything that would work.
Entire .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.html$
RewriteRule ^(.*)\.html$ $1 [R=301,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
You want to use a URL rewrite
RewriteEngine On
RewriteRule ^(.*)\.html$ $1
This should do it. It will rewrite a request to site.com/category/whatever.html to site.com/category/whatever. it shouldn't be dependent upon the requested file existing.
<Directory /var/www/category>
RewriteEngine on
RewriteRule (.*)\.html$ /category/$1
</Directory>
This is the format for apache2.conf or virtual host files. Not sure if you use the command in .htaccess. It's best to take care of it in the server conf, if you can, as that is only parsed once, on server startup, and htaccess is parsed on each request.