Windows 10 Xampp Apache - htaccess rewriterule not working - apache

I am using apache XAMPP on Windows 10 and am trying to get htaccess working. I have this so far...
RewriteEngine On
RewriteRule ^noexist/?$ /folder/
I want someone to go to
www.mysite.com/noexist/test.php -> www.mysite.com/folder/test.php
But I still want the URL to be www.mysite.com/noexist/test.php
I am just getting a 404, where am I going wrong? I have confirmed the htaccess file is being loaded by putting invalid code in and it throws an error so I am certain the file is being used.

RewriteRule ^noexist/?$ /folder/
The regex ^noexist/?$ matches noexist or noexist/ only, so /noexist/test.php is ignored by this rule. It also only rewrites to /folder/ only.
In other words, this rewrites /noexist (or /noexist/) to /folder/ only.
To rewrite /noexist/<something> to /folder/<something> then you need to capture the <something> part and pass this through to the target URL (i.e the substitution string). For example:
RewriteRule ^noexist/(.*) /folder/$1 [L]
The $1 backreference in the substitution string contains the URL-path captured by the parenthesised subpattern (ie. (.*)) in the RewriteRule pattern.
Don't forget the L (last) flag. (This is important if you have other directives later in the file.)
Note that this rewrite is unconditional, regardless of whether /folder/<something> exists or not. If you want to check that /folder/<something> exists before rewriting then add an additional condition. For example:
RewriteCond %{DOCUMENT_ROOT}/folder/$1 -f
RewriteRule ^noexist/(.*) /folder/$1 [L]
This assumes your .htaccess file is located in the document root.

Related

htaccess not working but check successful localhost

I have a simple .htaccessfile
DirectoryIndex index.php
RewriteEngine On
RewriteRule ^v4r.info/(.*)/(.*) v4r.info/NGOplus/index.php?NGO=$1&page=$2 [L,QSA]
I tested the file in htaccess.madewithlove.com, it gives a correct result and copy&pasting the result works flawlessly. (http://localhost/v4r.info/NGOplus/index.php?NGO=action-for-woman&page=board.list.php&ff=710;;;;;&startdate=2017-11-11)
But htaccess fails on localhost with an error:
File does not exist:
/var/www/html/public_html/v4r.info/action-for-woman/board.list.php
The test URL is
localhost/v4r.info/NGOplus/index.php?NGO=action-for-woman&page=board.list.php&ff=710;;;;;&startdate=2017-11-11
htaccess is active. (rubbish line gives "internal server error")
in another directory htaccess is working fine.
apache.conf seems ok (AllowOverride All)
Added:
The htaccess file is not in the base directory but in the 1. subdirectory (v4r.info).
What works is htaccess in v4r.info/NGOplus with a symlink 'action-for-woman' to NGOplus
RewriteRule ^(.+?)/?$ index.php?page=$1 [L,QSA]
Here, apache does a «local» rewrite, i.e. just the last part of the URL (the directory name 'action-for-woman' I have to extract from $_SERVER ...)
my .htaccess file is in v4r.info directory what is not the root directory.
In that case, your rule will never match. The RewriteRule pattern matches a URL-path relative to the directory that contains the .htaccess file.
But anyhow, rewriting is not recursive afaik.
Yes, it is "recursive" in a directory context (ie. .htaccess). In that the rewrite engine "loops" repeatedly until the URL passes through unchanged, or you have explicitly set END (Apache 2.4).
Try the following instead:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} !index\.php$
RewriteRule ^([^/]+)/([^/]+)$ /v4r.info/NGOplus/index.php?NGO=$1&page=$2 [L,QSA]
The check against the REDIRECT_STATUS environment variable is to ensure that only direct requests are rewritten and not already rewritten requests.
However, this pattern is still far too generic as it matches any two path segments. I put the 2nd condition that checks index.php just so you can request /v4r.info/NGOplus/index.php directly (as you were doing in your tests). However, this could be avoided by making the regex more specific.

how do I rewrite a URL and maintain the file name

I have a rewrite written in my .htaccess file. I am trying to redirect the following
https://olddomain.com/folder/file.pdf to https://newdomain.com/folder/file.pdf. file.pdf can change so I need to change the domain but leave the folder and file name needs to stay what ever it is. it could be file.pdf or file1.pdf etc
I have this code in my .htaccess file
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/folder/(.*)$
RewriteRule ^(.*) https://newdomain.com/folder/%1 [R=301,NC]
If the file.pdf exists on the old server then the redirect works but if the file does not exist on the old server the redirect does not work.
Any help fixing this would be appreciated.
If the file.pdf exists on the old server then the redirect works but if the file does not exist on the old server the redirect does not work.
That sounds like you've put the rule/redirect in the wrong place. If you have other directives before this redirect that implement a front-controller pattern then you will experience this same behaviour since any request for a non-existent file would be routed to the front-controller (and request for an existing file is ignored) before your redirect is triggered - so no redirect occurs.
If this is the case then you need to move your rule to the top of the file, before any existing rewrites.
RewriteCond %{REQUEST_URI} ^/folder/(.*)$
RewriteRule ^(.*) https://newdomain.com/folder/%1 [R=301,NC]
However, your existing rule is not quite correct. Importantly, you are missing the L flag on the RewriteRule directive and the preceding RewriteCond directive is not required. For example, try the following instead:
RewriteRule ^folder/.* https://newdomain.com/$0 [NC,R=301,L]
This does assume your .htaccess file is located in the document root of the site.
Alternatively, you create an additional .htaccess file inside the /folder with the following:
RewriteEngine On
RewriteRule ^ https://newdomain.com%{REQUEST_URI} [R=301,L]
The REQUEST_URI server variable contains the full URL-path of the request (including the slash prefix).
By default, the mod_rewrite directives in the /folder/.htaccess file will completely override any directives in the parent (root) .htaccess file (the mod_rewrite directives in the parent are not even processed).

Simulate directory with htaccess

When my main website opens, it retrieves content from /home/parsa/public_html.
I have tried this: rewriteRule "^/(.*)$" "/ppyazi.com/$1"
I need it to retrieve the files from /home/parsa/public_html/ppyazi.com without redirecting to it on the user side.
Here are some examples:
index.php to display contents of ppyazi.com/index.php
users/index.php to display contents of ppyazi.com/users/index.php
I have tried this: rewriteRule "^/(.*)$" "/ppyazi.com/$1"
In .htaccess the URL-path that is matched by the RewriteRule pattern does not start with a slash. So, the pattern ^/(.*)$ will never match and your directive does nothing.
However, unless there is also a .htaccess file in the /ppyazi.com subdirectory with mod_rewrite directives then you need to be careful of rewrite loops.
Try the following instead:
RewriteEngine On
rewriteRule !^ppyazi\.com\ /ppyazi.com%{REQUEST_URI} [L]
The RewriteRule pattern simply checks that the URL does not already start with the directory we are rewriting to. Instead of the $1 backreference (since we are not capturing anything in the RewriteRule pattern) we use the REQUEST_URI server variable instead. Note that REQUEST_URI contains the full URL-path, including the slash prefix, so the slash should be omitted from the susbstitution string.
The L (last) flag is required to prevent any further directives being processed that occur later in the file (in the current round of processing). If this is the last mod_rewrite directive in the file then it is superfluous. Note, however, that in .htaccess the rewriting process essentially starts over (until the URL passes through unchanged), so other directives might still process the request.

.htaccess and rewrite from subdirectories inside unknown parent directory

So I have an htaccess file in a subdirectory and whenever I try to rewrite the url, it redirects to the document_root and not the subdirectory where the htaccess resides. Now, under normal circumstances, I'd rewrite it with the path to the subdirectory with path/to/subdirectory, but I won't know what the exact path will be. Is there a way either, through an Apache environment variable or something else, to write out that path?
Edit:
Here's the .htaccess file so far.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule (.*-file) a/b/c/$1.file
RewriteRule (.*-file) $1.file
So, I'm trying to, if the request contains the word file, I want to match the entire request prior to the word file and redirect there. This is so that if a request is to
example.com/a/b/c/file[any characters here].file
the request will be redirected to the right file. To reiterate, the problem is that I am trying to redirect within the subdirectory. So when I say Rewrite $1, I want that to include the entire request and not just what matched in the REQUEST_FILENAME. And the reason I need it to do that is because I can't simply put a/b/c/$1.file since I won't know for absolute certainty the a/b/c part.
Edit 2: Examples:
So, an example is that I'd send a request like:
example.com/a/b/c/fileacs.file
And want to redirect to:
example.com/a/b/c/file.file
Where I do not know a/b/c/. I have an actual regex and set of rules for the real-world use of this redirect, so don't mind the ridiculous nature of this example.
But currently it's redirecting to:
example.com/file.file
Which does not exist and even if it did, I do not want to redirect there. I've read about Rewrite Context, but can't find out anything substantial about it nor if it's the cause for this. Thank you, in advance.
You can use this rule to capture any path before fileacs.file and use that as bach-reference in RewriteRule:
RewriteEngine On
RewriteCond ^(.*)/file[^.]+\.file$ [NC]
RewriteRule ^ %1/file.file [L,R=302]
The solution is to use the a RewriteCond on the %{REQUEST_URI} (thanks anubhava!) that checks matches the entire request except for the %{REQUEST_FILENAME} without capturing it, using a lookahead. Write out this with the %1 followed by the desired filename. See the following:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} (.*)-file(?!\.file) [NC]
RewriteRule ^ %1.file [L,R=301]
The %1 now holds the path up to the directory that the .htaccess is stored, plus any prefix to the filename. This doesn't match the remainder of the request, but rather looksahead to ensure you're not actually requesting the file you would like to redirect to (causing a loop).

mod_rewrite in .htaccess file for unknown first part of path

I am trying to write a rewrite rule to change path slugs to query parameters. It is for a web service, and should only rewrite this rule if the host starts with api. There are two slugs that I am trying to capture and rewrite. The first is optional and is a version (i.e. v1.2) and the second is the service domain (i.e. customers, transactions, etc.).
http://api.domain.com/v2.5/customers should rewrite to ?version=2.5&domain=customers
I also want to support a default version so that
http://api.domain.com/customers should rewrite to ?version=&domain=customers
Here is what my .htaccess file looks like:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^api\..*
RewriteRule ^v([\d\.]*)?\/?([^\/]*)$ ?version=$1&domain=$2
The first example above works fine, but I can't get the default version path to work. I have tried a ton of different things. I thought starting with ^.*v would help, but it didn't. Anybody know how to make it match when you don't know the starting characters?
Try:
RewriteCond %{HTTP_HOST} ^api\..*
RewriteCond %{QUERY_STRING} !version=
RewriteRule ^(v([\d\.]*))?\/?([^\/]*)$ /?version=$2&domain=$3 [L]
This makes the /v part optional:
/v2.5/foo -> /?version=2.5&domain=foo
/foo -> /?version=&domain=foo
/v/foo -> /?version=&domain=foo