PerlDancer / Dancer

The easiest way to write web applications with Perl (Perl web micro-framework)
http://perldancer.org/
737 stars 209 forks source link

request->uri_base contains dispatch.(f)cgi when Dancer is executed via DirectoryIndex (Apache 2.4) #1171

Open isync opened 7 years ago

isync commented 7 years ago

Dancer version 1.3202 Dunno if this is a bug or wanted behaviour:

On one Dancer site I recently had an issue where dispatch.fcgi ended up in _request->uribase, for example _request->uribase = "http://www.example.com/dispatch.fcgi"

By accident I found that this only happened at the root "/" path of the site... Which led me to why it happened: I had a new (over-optimisation!?) Directive in the site's Apache .conf file. Illustrated with the example from Dancer::Deployment, I had this:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/path/to/rootdir"

    <Directory "/path/to/rootdir">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
        AddHandler fastcgi-script .fcgi
    </Directory>

    DirectoryIndex    /dispatch.fcgi      # <<-- this here

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteRule /(.*)$     /dispatch.fcgi$1 [QSA,L]
</VirtualHost>

As suggested in the Dancer::Deployment docs, my .conf ended with every path going through the rewrite engine, with "RewriteRule ^(.*)$ /dispatch.fcgi$1 [QSA,L]". However, I decided to be extra smart, and that the root "/" doesn't need to be elaborately parsed, thus I set a DirectoryIndex directive at the beginning of the config file, to break out of testing the URL early.

That didn't work as expected! As it seems, when dispatch.fcgi is called via DirectoryIndex, ".../dispatch.fcgi" ends up in _request->uribase. Obviously Apache calls the script different via DirectoryIndex (without appending the path, right?). And when no URI path is appended, Dancer's _uribase() algorithm decides that the script name is part of the _uribase...

If that's the feature/problem, then why is my current over-optimisation working?

    ...
    RewriteRule ^/$         /dispatch.fcgi         [QSA,L]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-
    RewriteRule ^(.*)$      /dispatch.fcgi        [QSA,L]

The above "/"-edge-case-rewrite-rule is also passing nothing to dispatch.fcgi... Clearly, Apache handles scripts different via DirectoryIndex, and Dancer's _uribase() returns a different value.

shadowcat-mst commented 7 years ago

Yes, that's how DirectoryIndex works, and why I said you needed to use mod_rewrite. This was the very first diagnosis and solution I suggested before you spent an hour plus on other configs :P

By the time the request gets to Dancer we've no way of telling that you use DirectoryIndex that I can think of so unless you can see something in the PSGI environment that we could test, I don't think it's possible to change this behaviour, and the only assistance I can give you is "if at first you don't succeed, maybe try doing what mst suggested in the first place".

I'm not closing this immediately because I'd like to give others a chance to explain why I'm completely wrong, since I'd be happy to trade any dignity I have on this ticket for the pleasant surprise that this is fixable after all ;)

isync commented 7 years ago

Actually, took me more time to discuss the issue..., as once I stumbled over the behaviour again, I quickly discovered it to be related with DirectoryIndex. Anyway. As a final remark, let me emphasize that my intention wasn't to annoy you or anyone! So, really, thank you for looking into this again.