apacheurl-rewritingawstats

httpd RewriteRule not working as expected


On my server I am running awstats, a script that I can currently access via the following URL:

https://stats.example.com/bin/awstats.pl/?config=global

I am trying to use rewrite rules such that I can just use

https://stats.example.com/global

This is what I have defined for a rewrite rule

RewriteRule ^(.*)$ bin/awstats.pl/?config=$1 [NC,L]

httpd virtual host

# Address
ServerName              stats.example.com

# Rewrite
RewriteRule      ^(.*)$ bin/awstats.pl/?config=$1 [NC,L]

Options                 ExecCGI
AddHandler              cgi-script .cgi .pl
Alias                   /awstatsstuff "/path/to/awstatsstuff/"

<Directory "/path/to/awstatsstuff">
        Options ExecCGI
        AllowOverride None
        Order allow,deny
        Allow from all
</Directory>

The problem is that anything I try and access (besides the index), will give me a 400, and my apache logs show no errors.

Should this rule be working correctly, do I have a different configuration issue? Or am I missing something? Yes, RewriteEngine is on.


edit

Based on Michael Berkowski's comment I determined that is is infact an issue with resources also being directed to the pl script, I have since modified and am using the following:

RewriteCond             %{REQUEST_FILENAME} !-d
RewriteCond             %{REQUEST_FILENAME} !-f
RewriteRule             ^/([0-9a-z]+\.[0-9a-z]+\.[0-9a-z]+)$    bin/awstats.pl/?config=$1 [NC,L]

I can now load the page again using

https://stats.example.com/bin/awstats.pl/?config=www.example.com

This means that all resources can be loaded correctly, however

https://stats.example.com/www.exmaple.com

will return a 400 ( this does not come from the pl script which will return a 200 and error message if the specified config file can not be found, again, no error messages in the logs.


another edit

In changing [NC,L] to [R=302], I am provided with the correct redirect upon request,

curl -k "https://stats.example.com/a.b.c"
...
<p>The document has moved <a href="https://stats.example.com/bin/awstats.pl/?config=a.b.c">here</a>.</p>
...

Using [R=403] proves that the rewrite rule is working as expected

The problem that I am now facing is that when using [NC,L], I am still receiving a 400, with no errors available in the httpd log.


Solution

  • I strongly suspect requests for documents other than the index are being mistakenly trapped by the very permissive (.*) and sent to config= in error. The 400 (bad request) probably then results from awstats tripping over values it cannot handle there.

    Two things should take place. First, you need to exclude real existing files and directories from the rewrite, conventionally done with a pair of RewriteCond. Then, instead of the very general (.*) matcher, use a matcher more specific to the values that should actually be considered valid for config=.

    # If the requested document is not a known
    # file or directory on disk...
    RewriteCond %{REQUEST_FILENAME} !=f
    RewriteCond %{REQUEST_FILENAME} !=d
    
    # Rewrite patterns matching only the expected
    # config= values for awstats
    RewriteRule ^([a-z0-9]+\.[a-z0-9]+\.[a-z0-9]+)$ bin/awstats.pl?config=$1 [L,NC]
    

    Above I have used [a-z0-9]+\. to match 3 part FQDN strings as mentioned in the comment thread. That may need additional refinement. To also support the string "global" for example, you could expand it to

    RewriteRule ^(global|[a-z0-9]+\.[a-z0-9]+\.[a-z0-9]+)$ bin/awstats.pl?config=$1 [L,NC]