Use an external rewrite engine with apache - apache

I want to run a rewrite engine on my frontend servers (apache).
I have added this configuration
<If "-f 'PATH_TO_MY_LUA_SCRIPT'">
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteMap cust "prg:PATH_TO_MY_LUA_SCRIPT"
RewriteRule ^(.*)$ ${cust:%{REQUEST_URI}}" [QSA,L]
</IfModule>
</If>
But Apache says that RewriteMap not allowed here
PS : Of course PATH_TO_MY_LUA_SCRIPT is replaced by the full path (and my script is executable)
Has anyone used an external rewrite lua scriupt with Apache 2.4 ?

Of course, I forget to precise.
This conf is not in my .htaccess but in the main vhost config

See RewriteMap documentation
Context: server config, virtual host
And Context means
Context
This indicates where in the server's configuration files the directive is legal. It's a comma-separated list of one or more of the following values:
server config ...
virtual host ...
directory ...
.htaccess ...
The directive is only allowed within the designated context; if you try to use it elsewhere, you'll get a configuration error that will either prevent the server from handling requests in that context correctly, or will keep the server from operating at all -- i.e., the server won't even start.
So you cannot use RewriteMap in an .htaccess file, only in the main or in a virtual host configuration.
In this case If is causing the failure, because
Only directives that support the directory context can be used within this configuration section.
But RewriteMap may not be used in a directory context. So even if you have it in the main or virtual host configuration, you must not use it inside an If directive.

Related

Redirect all subdomains to file

I have a server to which many domains points. So I need a generic .htaccess rule. I need to create a .htaccess file which redirects all subdomains to their correspondent subdomain folder.
Is that possible? Thanks.
For example:
http(s)://apple.domain1.com -> https://domain1.com/redir/apple/index..html
http(s)://orange.2domain.co.uk -> https://2domain.co.uk/redir/orange/index.asp
http(s)://banana.doma3n.org -> https://doma3n.org/redir/banana/index.php
OK, so now it suddenly are three questions in one :-)
I don't really understand why you need separate folders for this. Why not one script that handles those requests, regardless on what host ("subdomain") is called? The script knows about what host has been called, so it can act accordingly.
Anyway, your question is how to rewrite to separate folders, so that is what I will answer to...
In addition to rewriting hosts acting as landing pages you also want to configure your default host (the fallback host) such that it delivers something that does make sense.
Anyway, this should point you into the right direction:
First you need to configure your DirectoryIndex:
DirectoryIndex index.html
DirectoryIndex index.php
DirectoryIndex index.asp
Consult the documentation for more details and where to place those directives:
https://httpd.apache.org/docs/2.4/mod/mod_dir.html
Second you need to rewrite the incoming requests to internal directories:
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REMOTE_ADDR} ^10\.
RewriteRule ^ /redir_internal [END]
RewriteCond %{HTTP_HOST} ^([^.]+)\.
RewriteCond -d %1
RewriteRule ^ /%1 [END]
RewriteRule ^ /something_that_acts_as_a_fallback
Consult the documentation for more details:
https://httpd.apache.org/docs/current/mod/mod_rewrite.html
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a distributed configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a distributed configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using distributed configuration files (".htaccess"). Those distributed configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

Trouble shortening my MediaWiki site URL? Where is <directory> directive?

I am using a basic hosting plan on Host Gator. I installed MediaWiki and I am getting URLs with index.php?title= in it, i.e. www.domain.com/index.php?title=Main_Page
I want to remove the index.php?title= part and just have the title of the page appear. I am following the instructions from http://www.mediawiki.org/wiki/Manual:Short_URL/Page_title_--_Windows_%26_Apache_without_403_on_Special_Pages, not sure if this is the right instructions I should be using.
Step 1 of the instructions indicate that "If you have vHosts configured, insert the following Rewrite directives into the appropriate <VirtualHost> directive. Otherwise, insert it in the <directory> directive for your wiki's root directory:" and to insert:
RewriteEngine On
RewriteRule ^/(.*):(.*) /index.php/$1:$2
Where is the <directory> directive located? What file should I be inserting the code into?
The <directory> block is a httpd.conf Apache configuration file directive.
On a shared hosting enviroment, you don't generally have directly access to his file. You still have access to an .htaccess file, which allows most configuration directives to be used.
Create a .htaccess at your web root (the same directory you have index.php and LocalSettings.php) and write the RewriteEngine / RewriteRules directives in this file.
If this fails, follow instead this guide, more adapted to your situation:
http://www.mediawiki.org/wiki/Manual:Short_URL/Apache

.htaccess in Multiple Environments

I know similar questions have been asked before but I haven't found any really specific answers for my situation.
I have an ExpressionEngine site running on multiple environments (local, dev, production), and each of those environments needs different .htaccess rules:
All Environments
Remove index.php
Set a 404 file
Set 301 Redirects
Development
Password Protect with .htpasswd
Force HTTPS protocol
Prevent search engine indexing with X-Robots-Tag
Production
Force HTTPS protocol
Redirect non-www subdomains to www
Local
No unique rules.
I've seen a lot of examples of how you can set specific environments per-module. Like RewriteCond %{REQUEST_HOST} ^dev.myurl.com for the mod_rewrite module, and tricks like this for .htpasswd requirements.
But what I would really prefer is some way to set global environment variables, then re-use those variables in the .htaccess file per-environment. To use pseudo-javascript as an example, something like:
var local = 'mysite.local';
var development = 'dev.mysite.com';
var production = 'www.mysite.com';
// Global .htaccess rules
if(environment == local){
// Local environment .htaccess rules
}
if(environment == development){
// Development environment .htaccess rules
}
if(environment == production){
//Production envirotnment .htaccess rules
}
This way all of the environment-specific rules are all grouped together, making a really clean file, and only one variable needs to be changed if an environment is changed.
I've seen a few references to altering settings in Apache's config files, but obviously that's not a viable option if I'm dealing with 3rd-party hosts.
So is this pie-in-the-sky wishful thinking, or can it be done?
Jon's answer is a good one. Unfortunately, not all web hosts will allow you to control that -D parameter for starting Apache.
Here's a way to use a single htaccess file on dev and production, but only have the dev site password protected:
# ----------------------------------------------------------------------
# Password protect staging server
# Use one .htaccess file across multiple environments
# (e.g. local, dev, staging, production)
# but only password protect a specific environment.
# ----------------------------------------------------------------------
SetEnvIf Host staging.domain.com passreq
AuthType Basic
AuthName "Password Required"
AuthUserFile /full/path/to/.htpasswd
Require valid-user
Order allow,deny
Allow from all
Deny from env=passreq
Satisfy any
So is this pie-in-the-sky wishful thinking, or can it be done?
IMO, yes. You're never going to be able to get predictable "scoping" of rules based on ENV variables or anything like that. There doesn't exist arbitrary if(something) { do everything in here } in apache. Lots of directives won't work inside certain scopes, and in later on, when you need to change how something works, you're more likely to break what you have than simply amending it.
The best way is to not use htaccess files at all:
You should avoid using .htaccess files completely if you have access to httpd main server config file. Using .htaccess files slows down your Apache http server. Any directive that you can include in a .htaccess file is better set in a Directory block, as it will have the same effect with better performance.
Create a separate vhost for local, dev, and production. Turn them on or off as needed, whatever global config they share, store that elsewhere (like in a file called global.includes) and then use the Include directive in all 3 vhosts. If you need to apply rules to specific directories, use the <Directory> block instead of htaccess files.
If you'd rather stick everything inside htaccess files, you could try putting everything in <IfDefine> blocks, it's probably the closest thing you'll have to your pseudo-code in your question. Essentially something like:
# Global htaccess rules
RewriteEngine On
RewriteRule ^foo$ /bar [L]
# Only local
<IfDefine LocalInstance>
RewriteRule ^local/foo /bar [L]
</IfDefine>
# Only dev
<IfDefine DevInstance>
RewriteRule ^dev/foo /bar [L]
</IfDefine>
# Only production
<IfDefine ProductionInstance>
RewriteRule ^dev/foo /bar [L]
</IfDefine>
Then when you start apache, you'd need to pass in -DLocalInstance, -DDevInstance, or -DProductionInstance as command line paramaeters or using the Define directive (with only one argument) somewhere in your vhost config. This isn't guaranteed to work as smoothly as it looks like it should, I've ran into unexplained issues with <IfDefine> before, especially if you try to get too fancy.

Apache Mod_ReWrite Suddenly Stopped Working

I had mod_rewrite set on my server to rewrite a url like the following
http://www.example.com/1
to
http://www.example.com/index.php?show=1
In order words a URL shortern. Everything was working fine when the system was running under a sub-domain on my development site, but now it just generates a Not Found error, although if I manually enter the url /index.php?show=1 it works fine.
So the only changes is the urls switching from
http://www.site.example.com
to
http://www.site.com
however it's still running on the same server and the same sub-folder inside public_html on the server just the new domain name has been pointed to that folder.
The folder it's stored in is /public_html/paste
The full .htaccess file running in the directory is
# Set Default File
DirectoryIndex index.php
# Turn ReWrite Engine On
RewriteEngine on
# Create Rule To Write URLs To Shorter Versions
RewriteRule /([a-z0-9]+) /index.php?show=$1
I can't enable RewriteLog as the hosting doesn't allow it for some reason.
It sounds like the AllowOverride directive is not properly set for that folder. In your Apache configuration, you should make sure that the Directory or Vhost you're using for the primary domain has the AllowOverride set to All
http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride
You probably need to specify the RewriteBase directive.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
I'll also note that Options +FollowSymlinks would be good to have in there too in case you ever turn it off further up the config chain (rewrite wont work without it).

Reverse Proxy in CakePHP?

I've got a CakePHP application, and the following directives in my httpd.conf
ProxyRequests off
ProxyPass /forum/ http://somesite.com/phpbb3
ProxyPass /gallery/ http://someothersite.com/gallery3
<Location /forum/>
ProxyPassReverse /
</Location>
<Location /gallery/>
ProxyPassReverse /
</Location>
Without CakePHP this works fine - but because CakePHP is using it's own redirection logic from routes.php and other sources, it seems to override any proxy settings, so any call to "/community" on my server follows the default pathway of looking for a Controller called CommunityController.
My issue here is that I want to have one server that serves muliple applications, but keep it seamless to the user - so a complete PHPBB application can for instance run within the "/forum" directory as if it were a controller in CakePHP.
Has anyone done this before, and can it be done? Why does mod_rewrite and/or the routes.php file override my mod_proxy directives??
Perhaps instead of using mod_proxy, you could use mod_rewrite to create a RewriteRule directive with the [P] (proxy) flag in conjunction with the [L] (last rule) flag.
'proxy|P' (force proxy):
This flag
forces the substitution part to be
internally sent as a proxy request and
immediately (rewrite processing stops
here) put through the proxy module.
You must make sure that the
substitution string is a valid URI
(typically starting with
http://hostname) which can be handled
by the Apache proxy module. If not,
you will get an error from the proxy
module. Use this flag to achieve a
more powerful implementation of the
ProxyPass directive, to map remote
content into the namespace of the
local server.
Note: mod_proxy must be enabled in
order to use this flag.
'last|L' (last rule):
Stop the
rewriting process here and don't apply
any more rewrite rules. This
corresponds to the Perl last command
or the break command in C. Use this
flag to prevent the currently
rewritten URL from being rewritten
further by following rules. For
example, use it to rewrite the
root-path URL ('/') to a real one,
e.g., '/e/www/'.