How to stop htaccess rewrite rule updating browser URL - apache

I've read through many of the similar requests such as:
Apache rewrite rule - prevent rewritten URL appearing in browser URL bar
But I can't figure out what I'm doing wrong, any help would be much appreciated.
I'm using codeigniter 3 and it's root is at the following location:
https://example.com/api/v1.0
I've set up a basic route and all is working fine with Codeigniter E.g. If I navigate to:
/api/v1.0/index.php/pages/view/about
the appropriate page appears so all seams well. What I really want is for the URL to get rewritten so that when I enter:
/api/v1.0/pages/view/about
it goes to the same page. I've added a htaccess file that rewrites the rule and all works as expected:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /api/v1.0/
RewriteCond $1 !^(index.php|resources|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
The problem is, when I enter the the url:
/api/v1.0/pages/view/about
it goes to the correct page, but the browser URL gets updated to:
/api/v1.0/index.php/pages/view/about
My question is, how can I stop the browser URL from being updated?
Update - my web servers site behind an AWS ELB that acts as the https end point. I have the following in the httpd.conf to ensure that any non 'www' prefixed URLS and any http calls are redirected to https://www
<VirtualHost *:80>
RequestHeader set X-Forwarded-Proto "http"
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} !^test\. [NC]
RewriteCond %{HTTP_HOST} !^signup\. [NC]
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
I don't think this rule is causing an issue as its not being invoked, I'm providing the correct prefix and protocol.
Many thanks in advance,
Rob

Check that index.php isn't set for $config['index_page'].
If it is change it to:
$config['index_page'] = '';

OK, after much testing it would appear that my virtual host settings in httpd.conf were causing the issue. If I removed these rules and then the local .htaccess rules worked exactly as expected.
I've removed the local .htaccess rules and added the following to rule to httpd.conf:
RewriteRule ^/api/v1\.0/([A-Za-z0-9-/]+)/?$ /api/v1.0/index\.php/$1 [NC,L,QSA] # Process API Call
My Virtual Host section now looks like this:
RequestHeader set X-Forwarded-Proto "http"
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} !^test\. [NC]
RewriteCond %{HTTP_HOST} !^signup\. [NC]
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteRule ^/api/v1\.0/([A-Za-z0-9-/]+)/?$ /api/v1.0/index\.php/$1 [NC,L,QSA] # Process API Call
So now calls to:
/api/v1.0/some/directory
Will get rewritten to this:
/api/v1.0/index.php/some/directory
And this happens without redirecting the browser or affecting the browser URL. What I don't understand is why this is not entering into an infinite loop as I have no rewrite precondition to check for calls to the /api/v1.0/index.php/*
Anybody know why this is no entering into an infinite loop?

Related

URL rewrite with HTTPS / www not working for subpages

I have to following configuration in my .htaccess. The first rule puts https before the URL and the second puts www before the URL, if not set already.
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
These redirects work perfect for the homepage. However, if you call a subpage, these rules wont work.
domain.xy -> https://www.domain.xy (works, Homepage)
domain.xy/contact -> http://domain.xy/contact (doesnt work)
The weird thing is, the favicon get redirected correctly. Example with the contact page, as seen on
this picture.
How can it be, that my configuration only works for the toplevel, not for any subpage?
I'd say your RewriteRule is wrong. It should be .* instead of ^:
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The problem was another rule in the .htaccess-File. Our hosting provider automatically generates a .htaccess suiting the Typo3 installation. I had to place my rewrite rule before the following lines:
# If the file/symlink/directory does not exist => Redirect to index.php.
# For httpd.conf, you need to prefix each '%{REQUEST_FILENAME}' with '%{DOCUMENT_ROOT}'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]
This rules, as far as i understand, redirects any request, which is not a file, directory or symlink back to the index.php. So in my case if i call domain.xy/contact, it redirects back to the index.php.
Because this rule has the [L] flag at the end, the .htaccess stops processing here. So i moved both my rules above this block and they get called before this block comes to action.

Keep path when rewriting with .htaccess

I recently moved my webpage from HTTP to HTTPS and I now got a couple of things that doesn't work like before.
The problem I'm having is that when a user is trying to go to:
http://example.com/i/<imageID> they are redirected to:https://www.example.com/i/image.php?id=<imageID>. This is "correct", but not what I want. I want the links to stay at /i/<imageID> regardless of the user came from http or https.
I have two .htaccess-files that I use to control this redirection on my webpage.
First .htaccess (root directory):
RewriteEngine on
RewriteOptions inherit
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Second .htaccess (image directory - /i):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^=]+)$ image.php?img=$1 [NC,L]
This redirection was working just fine before I added the first .htaccess-file that redirects the user from HTTP to HTTPS, but now it seems to be broken.
I'm not that familiar with htaccess-files so I hope someone out there can help so I can get my clean URLs back. :)
UPDATED ANSWER --> updated again
%{REQUEST_URI} only includes the URI WITHOUT the querystring. But this is stored in and can be retrieved in another variable --> %{QUERY_STRING}
I edited the code accordingly for the first .htaccess-file
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI}%{QUERY_STRING} [L,R=301,QSA]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}%{QUERY_STRING} [L,R=301,QSA]
If you change your second .htaccess file to the following, it should be clean :)
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/i/image.php
RewriteRule ^/i/(.*) /i/image.php?img=$1 [P,NC,L,QSA]
The [P] stands for 'proxy' meaning that your Apache is seen by the client as a proxy (ofc, without his notice), because your Apache executes the actual (correct) request, while the client only sees the result.
My new take on your problem
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^(.*)$ https://%2$1 [R=Permanent,L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^=]+)$ image.php?img=$1 [NC,L]

Stop .htaccess redirecting everything to

I have setup my .htaccess to redirect requests from http ://subdomain.domain.com.tld, http ://www.subdomain.domain.com.tld and http ://domain.com.tld/folder (folder that contains contents of subdomain) to https ://subdomain.domain.com.tld so my single domain SSL certificate setup for subdomain.domain.com.tld is used at all times.
My problem is http ://domain.com.tld also redirects to https ://subdomain.domain.com.tld. How do I stop this?
RewriteOptions inherit
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^subdomain.domain\.com.tld
RewriteRule ^(.*)$ https://subdomain.domain.com.tld/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^.*$
RewriteRule ^folder$ "https\:\/\/subdomain\.domain\.com\.tld\/" [R=301,L]
Thank you.
These rules should replace everything after RewriteEngine on:
RewriteCond %{HTTP_HOST} ^(www\.)?subdomain\.domain\.com\.tld$ [NC]
RewriteRule ^(.*)$ https://subdomain.domain.com.tld$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^domain\.com\.tld$ [NC]
RewriteRule ^folder/?(.*)$ https://subdomain.domain.com.tld$1 [R=301,L]
The first set of rules matches http://subdomain.domain.com.tld and http://www.subdomain.domain.com.tld
The second set matches http://domain.com.tld/folder, but does not match http://domain.com.tld without the "folder" part.
Edit: Corrected typo as noted in comments and escaped dots in RewriteConds.

.htaccess rewrite to simultaneously change domain and remove path

My URL structure is currently as follows:
http://domain.com/folder/filename (CURRENT)
I want to change this so that I can use the following URL instead:
http://sub.domain.com/filename (NEW)
So accessing the CURRENT or the NEW url, should load the file located at the CURRENT url, but show the NEW url in the address bar. It should only apply to the "/folder/" path.
sub.domain.com is a mirror of domain.com, ie. they share the same file system and root directory.
This is what I have so far:
Options +FollowSymLinks
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www.)?domain.com$ [NC]
RewriteCond %{REQUEST_URI} ^/folder/?(.*)$ [NC]
RewriteRule ^(.*)$ http://sub.domain.com/$1 [R=301,L]
This is working, but is missing the rule to remove the "/folder/" from the path. I've tried combining multiple RewriteRule's with no luck. Any ideas? Thanks.
UPDATE: Thanks again #Gerben - I understand what your rules are doing now, but the second one isn't working for me. I suspect because it's conflicting with some other rewrite rules, in particular those of WordPress, which are lower down in my .htaccess file:
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Because of this the page ends up in a redirect loop, ie (from Chrome):
"The webpage at http://sub.domain.com/folder/index.php has resulted in too many redirects." - while the url I was originally trying to access was, for example, http://sub.domain.com/page
Any ideas?
Try:
RewriteCond %{HTTP_HOST} ^(www.)?domain.com$ [NC]
RewriteRule ^(folder/)?(.*)$ http://sub.domain.com/$2 [R=301,L]
This will redirect everything to sub.domain.com, and remove the /folder part of the URI if it is there. If not, it redirects and leaves the URI untouched.
RewriteCond %{THE_REQUEST} /folder/
RewriteRule ^folder/(.*)$ http://sub.domain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^sub\.domain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule ^(.*)$ folder/$1 [L]
# WordPress rules here
edit the second R=301 should not have been there
But this won't work, as wordpress has no way of knowing you want folder. You could add the Proxy flag to the rewrite, but then you need to change the rule above to not redirect on this internal proxy request.

How to properly force HTTPS on specific pages using Apache

I would like to force my signup page to https, and allow all other pages to be browsed using https or http (e.g., http://www.example.com/signup should redirect to https://www.example.com/signup). I was able to force all pages to https, but cannot get only one page to redirect to https. The page just loads normally as http.
Here's the code I've been trying to use in my htaccess file:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^/signup(/.*)$ https://www.example.com/$1 [R=301,L]
For what it's worth (in case there is a conflict I'm unaware of), I am also using the following code to force all pages to redirect to www and to drop the .php from the file names in the URL:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^([a-z.]+)?example\.com$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .? http://www.%1example.com%{REQUEST_URI} [R=301,L]
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php?/$1
Any thoughts on what I'm doing wrong?
Have your https rule like this:
RewriteCond %{SERVER_PORT} =80
RewriteRule ^(signup/?)$ https://www.example.com/$1 [R=301,L,NC]
Remember that there is no starting slash / in RewriteRule.