.htaccess doesn't pass arguments to url - apache

I was trying to make my server redirecting to a single page every request the user asks.
The way I am doing it is this:
# Turn rewriting on
Options +FollowSymLinks
RewriteEngine On
# Redirect requests to py-server.php if the request is that page (to avoid loops)
RewriteCond %{REQUEST_URI} !=/py-server.php
# Check if it is not an asset that the page requested needs
RewriteCond %{REQUEST_URI} !.*\.png$ [NC]
RewriteCond %{REQUEST_URI} !.*\.jpg$ [NC]
RewriteCond %{REQUEST_URI} !.*\.css$ [NC]
RewriteCond %{REQUEST_URI} !.*\.gif$ [NC]
RewriteCond %{REQUEST_URI} !.*\.js$ [NC]
# Finally, redirects to the page by adding to the URL the path originally requested
RewriteRule ^(.*)$ /py-server.php?path=$1 [L,QSA]
I added some comments to clarify why I've written those lines.
Now, that code is made by pasting various codeblocks from the internet, but it should work from what I read around.
The fact is that the server redirects correctly to the right page, but without the path in the URL (= there isn't the path argument at all).
Note: the .htaccess file is located at the root directory of the site in localhost (I use XAMPP for the server); the request I'm referring to is, simply, the request of any file of the server like /index.php, /some_dir/, /some_dir/index.php;
Did I forgot something to add? or did I make a mistake anywhere?

Alright, I found the solution searching here and there again:
# Turn rewriting on
Options +FollowSymLinks
RewriteEngine On
# Redirect requests to py-server.php if the request is that page (to avoid loops)
RewriteCond %{REQUEST_URI} !=/py-server.php
# Check if it is not an asset that the page requested needs
RewriteCond %{REQUEST_URI} !.*\.png$ [NC]
RewriteCond %{REQUEST_URI} !.*\.jpg$ [NC]
RewriteCond %{REQUEST_URI} !.*\.css$ [NC]
RewriteCond %{REQUEST_URI} !.*\.gif$ [NC]
RewriteCond %{REQUEST_URI} !.*\.js$ [NC]
# Here, this is the line that does the job!
RewriteRule ^(.*)$ /py-server.php?path=%{REQUEST_URI} [R=302,NC]
I solved by putting %{REQUEST_URI} as an argument for the original path to pass and the R=302 flag between squared brackets.
All this code works perfectly, now: redirects ALL the requests to a file.php EXCEPT FOR the assets (JS files, images, GIFs, CSS files...) and the actual final file to avoid loops.
Edit: as MrWhite wrote in the comments, the only problem seems to have been the R=302 flag, because $1 and %{REQUEST_URI} would work in both cases with just a little difference.

Related

Apache .htaccess subdomain redirect + path proxying (rule chaining?)?

I've got a tricky question, as far as I see it ;)
Currently, I'm in setup of a dynamic branch release pipeline which already takes a branch during pipeline processing and deploys it on our test server in a reserved folder ("branches").
Our wildcard domain points towards it.
Currently working (in the branches folder):
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+)\.domain\.com$ [NC]
RewriteRule ^ %1%{REQUEST_URI}/public [L,NC]
But the problem now is, that for example a domain my-new-testbranch-123.domain.com get's the redirect to my-new-testbranch-123.domain.com/my-new-testbranch-123/public/. This is on one side ok (because out data is being found there, but I want to have a proper url such as the app can be routed properly. So I tried to rewrite the url via proxy. But without luck.
Any suggestions?
My goal would be to use the subdomain my-new-testbranch-123.domain.com/ without any additional path in url. The document root is located in my-new-testbranch-123/public/.
I tried via chaining, but both did not work as I thought -.-:
RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+)\.domain\.com$ [NC]
RewriteRule ^ %1%{REQUEST_URI}/public [NC,N]
RewriteCond %{REQUEST_URI} ([^.]+)/public
RewriteRule ^(.*)$ / [P]
and
RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+)\.domain\.com$ [NC]
RewriteRule ^ %1%{REQUEST_URI}/public [NC,C]
RewriteCond %{REQUEST_URI} ([^.]+)/public
RewriteRule ^(.*)$ / [P]
(with C and N flags)
Best,
Bent
Issue with your original rule is you don't have / after public and since that is an actual directory, Apache is doing a 301 redirect via mod_dir module.
You can use this rule to fix the issue:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+)\.domain\.com$ [NC]
RewriteRule ^ %1/public%{REQUEST_URI} [L]
Make sure to test in a new browser or via command line curl to avoid old browser cache.

How to have fake short urls but let apache get files from old directory?

We have a tool that unfortunately has to be set up in a subfolder - so it can't be moved to the root without a lot of effort. Even if it could, we would have unsightly URLs with parameters attached.
The current setup is something like this:
https://example.com/subfolder1/subfolder2/file.php?page=home
Nicer would be:
https://example.com/home/
Now we have the following RewriteRules:
RewriteEngine On
# www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ %{REQUEST_SCHEME}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
# add slash to the end
#RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]`
RewriteRule ^home/$ /subfolder1/subfolder2/file.php?page=home&param1=foo&param2=bar
RewriteRule ^contact/$ /subfolder1/subfolder2/file.php?page=contact&param1=foo&param2=bar
RewriteRule ^appointments/$ /subfolder1/subfolder2/file.php?page=appointments&param1=foo&param2=bar
So the URL https://example.com/home/ is currently "working" - at least the content of the page is there, but of course all relatively used elements (images, JS, CSS, ...) now lead to nowhere because e.g. https://example.com/home/images/ or https://example.com/home/js/ don't exist.
We have tried several other rules to tell Apache "show /home/ but take all other files from /subfolder1/subfolder2/". A few times the whole page was not reachable.
Currently these are the last lines in the htaccess:
RewriteCond %{DOCUMENT_ROOT}/subfolder1/subfolder2/%{REQUEST_FILENAME} -f
RewriteRule (.*) %{DOCUMENT_ROOT}/subfolder1/subfolder2/$1 [L]
What is wrong here? How should it be correct? And why? :)

Keep URL request but adjust server path

How can I achieve the following:
I have two domains hosted within the same web root path on the server. Usually php manages my HTTP_Hosts dynamically. Related to my question I am using the directory lisings function of apache. Each Request for /peter/ should point effectively to a different directory.
example.com/peter/ -> /peter_example.com/
xamplee.com/peter/ -> /peter_xamplee.com/
The Url should always contain /peter/ but in effect link to the respective real path which I'd like to have hidden.
Thank you!
Finally, after getting into regex and into mode_rewrite the hard way I can come up with the solution all by myself:
Options -MultiViews
RewriteEngine On
RewriteBase /
# Force adding a trailing Slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^peter/(.*)$ /peter_example\.com/$1 [NC,L]
RewriteCond %{HTTP_HOST} ^www\.xamplee\.com$ [NC]
RewriteRule ^peter/(.*)$ /peter_xamplee\.com/$1 [NC,L]

RewriteCond "except for directory" failing in complex rule set

I need to force everything except IE8 to HTTPS and IE8 specifically to HTTP
(it's temporarily - hence the 302 - its stupid, but there are legit business reasons).
I want all of this to ignore the /api/ directory as the app that utilizes these sadly doesn't follow redirects.
The following is working, IE8 detection is working. Everything is except /api/whatever is still being redirected.
I'd really appreciate any advice or an explanation of why this is not working.
# make sure mod_rewrite is ON
RewriteEngine On
# force staging and live to SSL
RewriteCond %{HTTPS} !=on
# Unless its IE 8
RewriteCond %{HTTP_USER_AGENT} !compatible;\sMSIE\s8\.0 [NC]
RewriteCond %{HTTP_HOST} ^(www\.|staging\.)?example\.com [NC]
# Skip the API
RewriteCond %{REQUEST_URI} !^/api/.*
# 301 Permanent
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
# force IE8 to Non-SSL
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_USER_AGENT} compatible;\sMSIE\s8\.0 [NC]
RewriteCond %{HTTP_HOST} ^(www\.|staging\.)?example\.com [NC]
# Skip the API
RewriteCond %{REQUEST_URI} !^/api/.*
# 302 Temporary
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [L,R=302]
Don't see anything wrong, though assuming that you've cleared your browser's cache, you could try a different approach and include an explicit pass-through at the top of your list of rules:
RewriteRule ^api/ - [L]
You can add that right under RewriteEngine On and get rid of the /api conditions.
The RewriteCond %{REQUEST_URI} !^/api/.* was working, the problem was a later rewrite routing everything through a front controller /index.php was causing the htaccess to reparse.
Changing the rule to RewriteCond %{REQUEST_URI} !^(/api/|/index.php) solved the problem. the front controller, index.php isn't callable directly anyway, so it's not an issue.

.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.