Simulate directory with htaccess - apache

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.

Related

rewrite request for /folder to folder/index.php without 301 redirect with apache

So I put an index.php in /pipe/index.php
I'd like to rewrite (internal, not redirect)
https://host/pipe?token=abc to https://host/pipe/index.php?token=abc
what I tried (caveat, assumes there is always a ? in the url):
RewriteEngine on
RewriteRule "^([^?]*)(.*)$" "$1/$2" [PT]
my hope was to split at the ? and just insert a / there.
But it seems apache finds out that "oh, pipe is a folder" before checking my .htacces (?) Because despite my [PT] it still redirects with 301 to /pipe/?token=abc, when I hoped for internal rewrite.
But it seems apache finds out that "oh, pipe is a folder" before checking my .htacces (?)
Yes, mod_dir will append the trailing slash with a 301 redirect. Although this occurs after mod_rewrite has processed the URL (if indeed it is being processed at all - see below). (The PT flag is irrelevant in .htaccess, since the resulting rewrite is passed through as a URL-path by default.)
RewriteRule "^([^?]*)(.*)$" "$1/$2" [PT]
However, your existing rule (by itself) would result in a rewrite-loop (500 Internal Server Error) since it matches itself and repeatedly appends a slash. If you are seeing a 301 redirect as mentioned above then either this rule is not doing anything (are .htaccess overrides enabled?) or you have a conflict with other rules.
As you've stated, this rule also assumes that the query string (with leading ?) is also matched by the RewriteRule pattern. The RewriteRule directive matches against the URL-path only, not the query string. $2 in the above rule is therefore always empty (unless you have %3F in the URL-path, ie. a %-encoded ?).
The query string is contained in its own variable, QUERY_STRING. But you simply want to pass through the same query string, so you don't need to do anything special here, since that happens by default.
Solution
To prevent mod_dir appending the trailing slash, you need to set DirectorySlash Off at the top of the root .htaccess file.
Note that these directives must go in the .htaccess file in the root/parent directory, as opposed to the subdirectory that has the trailing slash omitted. This is because the mod_rewrite directives (that "fix" the URL by appending the trailing slash) would never actually be processed in the subdirectory .htaccess file. The trailing slash would seem to be required for mod_rewrite to function. (However, the mod_dir DirectorySlash Off directive would still be processed successfully, so the slash would not be appended.)
For example:
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
# Must disable directory listings when "DirectorySlash Off" is set
Options -Indexes
However, you need to then manually append the trailing slash to any directory, where it is omitted, with an internal rewrite to "fix" the URL (and to correctly serve the DirectoryIndex document, ie. index.php).
# Ensure DirectoryIndex is set correctly
DirectoryIndex index.php
RewriteEngine On
# Append trailing slash to any directory where it has been omitted
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [L]
The trailing slash on the directory (via the internal rewrite) is required in order to serve the DirectoryIndex document, otherwise, you get a 403 Forbidden, even if the DirectoryIndex document is present.
If the trailing slash is omitted and directory listings (mod_autoindex) are enabled (disabled above) then a directory listing would be generated even if a DirectoryIndex document is present in that directory. (Which is why directory listings must be disabled when DirectorySlash Off is set.)
NB: You will need to make sure the browser cache is cleared since the earlier 301 redirect by mod_dir to append the trailing slash will have been cached by the browser.
This probably is what you are looking for:
RewriteEngine on
RewriteRule ^/?pipe/?$ /pipe/index.php [QSA,L]
The QSA flag is actually redundant here, it is the default, but it makes things clearer if you compare it to that variant (both work):
RewriteEngine on
RewriteRule ^/?pipe/?$ /pipe/index.php?%{QUERY_STRING} [QSD,L]
The documentation of the rewriting module, more specific of the RewriteRule directive clearly points out that the query string is not part of the path the rule's pattern is matched against.
If you want to have more control about the content of the query string you can use a RewriteCond:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^token=(.*)$
RewriteRule ^/?pipe/?$ /pipe/index.php?token=%1 [QSD,L]
Also you might want to redirect the original URL:
RewriteEngine on
RewriteRule ^/?pipe/index.php /pipe [QSA,R=301,END]
RewriteRule ^/?pipe/?$ /pipe/index.php [QSA,L]
And finally you might also want to take a look at the DirectoryIndex directive which might offer a solution without any rewriting at all, though this depends a bit on your setup ...

Windows 10 Xampp Apache - htaccess rewriterule not working

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.

Apache rewrite slash

I want to create rewrite rule(s) that catches couple of urls and redirects them depending if the content is available on the first location. If not, then call a url on the application so that it will regenerate it (and next time we can access it from the hard drive).
Let me insert the code here, so it will be easier to understand:
# I need to catch more than one page (and it has to work with and without the trailing slash!)
RewriteCond %{REQUEST_FILENAME} ^(/?|/page1/?|/page2/subpage/?)$ [NC]
# If the content exists
RewriteCond "%{DOCUMENT_ROOT}%{REQUEST_FILENAME}" -f
# Go to the exported folder and try to serve the page from there
# The first slash problem is here: if I have trailing slash, it will not work, because it will try to go here: /var/www/contentstatic/export/sites/default/$1//index.html
RewriteRule ^(.*)$ /var/www/contentstatic/export/sites/default/$1/index.html
# Otherwise run this rule (regenerate the file)
# This has to be changed (to something), because this will catch anything, but I need only the paths I defined earlier: ^(/?|/page1/?|/page2/subpage/?)$ <- Also I have to make sure the that last trailing slash is not there
RewriteRule ^(.*)$ http://application1:8080/export/sites/default/$1/index.html [P]
# At the bottom of the VirtualHost, there is another application that catches all the requests by default, so that's why I shouldn't use the "^(.*)$" in the previous RewriteRule
RewriteRule ^/(.*) http://application2:8080/$1 [P]
ProxyPassReverse / http://application2:8080/
The problems I have here:
This has to work with and without the trailing slash
I have to specify exactly what URLs to be served up from the /var/www/ folder or from the /export/sites/default folder, because if I don't do that the default application tries that, but it will fail
I also tried to remove the trailing slash from the url if it is there (in the first RewriteRule), but this rule:
[^/](.*)[^/]
changed the url from this: /page2/ to this: age2, so it removed the slashes and the first and last character.
Is it possible to use the same "^(/?|/page1/?|/page2/subpage/?)$" paths in the 3rd and 4th RewriteRule without repeating them?
Thanks

simple 301 redirect with variable not working, why?

Here's what I got so far. The first part works but not the redirect itself.
What do I need to do to make it work?
RewriteEngine On
RewriteRule ^([^/\.]+)/?$ page.php?name=$1 [L]
RewriteRule ^page.php?name=([^/\.]+)/?$ /$1 [R=301,L]
Also if I have multiple of these rules do I leave the [L] only on the last one?
Besides the first rule overriding the second one, your second rule also won't work because you're trying to match the query string in a RewriteRule. Try something like this instead:
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^name=([^/.&]+)/?$
RewriteCond %{ENV:REDIRECT_LOOP} !1
RewriteRule ^page\.php$ /%1? [NS,R=301,L]
RewriteRule ^([^/.]+)/?$ page.php?name=$1 [NS,QSA,E=LOOP:1]
(I included the QSA flag so that an URL like /foobar?foo=bar will be rewritten to /page.php?name=foobar&foo=bar instead of just /page.php?name=foobar. If you don't want that, leave it out.)
Note: The second RewriteCond is there to keep the first rule from matching again after the second one has matched. The problem is that, in .htaccess context, mod_rewrite acts more or less as if all rules had the PT flag, causing the ruleset to be rerun from the start after every rewrite, even internal ones. Or, to quote the documentation:
"If you are using RewriteRule in either .htaccess files or in <Directory> sections, it is important to have some understanding of how the rules are processed. The simplified form of this is that once the rules have been processed, the rewritten request is handed back to the URL parsing engine to do what it may with it. It is possible that as the rewritten request is handled, the .htaccess file or <Directory> section may be encountered again, and thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect - either internal or external - causing the request process to start over."
The workaround I'm using is to set a custom environment variable with E=LOOP:1 when the internal rewrite triggers, and check for it before doing the external rewrite. Note that, when the request processing restarts after the internal rewrite, Apache prepends REDIRECT_ to the names of all environment variables set during the previous pass, so even though the variable we set is named just LOOP, the one we need to check for is REDIRECT_LOOP.

What's wrong with my RewriteRule via .htaccess? (Why does it need RewriteBase?)

rewriteengine on
rewriterule ^/a/b$ ^/c$
not working,but
rewriteengine on
rewritebase /
rewriterule ^a/b$ ^c$
works.
It's probably not the RewriteBase that makes the rule work so much as the leading slash. Also, the second argument to RewriteRule isn't a regular expression. Instead, try:
RewriteRule ^/?a/b$ c
When applying a RewriteRule from .htaccess, the leading slash will be stripped from the URL, which will cause the pattern to fail if you include it. By starting a pattern with "^/?", it will work in the main configuration files and in per-directory config files.
Read over the detailed mod_rewrite documentation for the details of how the rewrite engine works and the significance of RewriteBase.
Edit:
As mentioned in the mod_rewrite technical details and described in the documentation for RewriteRule and RewriteBase, the URL has been translated to a path by the time the per-directory rewrite rules are evaluated. The rewrite engine no longer has a URL to work with. Instead, it removes the local directory prefix (the directory holding the .htaccess file), which ends with a slash. For example, suppose a visitor requests "/var/www/foo/bar/baz.html" and there is a rewrite rule set in "/var/www/foo/.htaccess". Fore each rule, the rewrite engine will strip "/var/www/foo/", leaving "bar/baz.html" to be matched against the rewrite rule. After processing a rule, the local directory prefix is prepended (unless the replacement begins with "http://"). After all the rewriting rules have been processed, the rewrite base, if set, replaces the local directory prefix; if not, the document root is stripped. The rewritten URL is then re-injected as a sub-request.
What version of Apache are you using? RewriteBase should not be necessary when you are rewriting from the root. If you are not, you may need it. For instance, a part of my current configurations (Apache 2.2) for one of my blogs looks as follows, and works:
RewriteEngine On
RewriteRule ^/$ /blog/ [R]
RewriteRule ^/wordpress/(.*) /blog/$1 [R]