How to use apache2 mod_rewrite within a Directory directive that uses wildcards?

后端 未结 1 1171
傲寒
傲寒 2021-02-13 17:44

I have written a web application which I run under a dedicated server for hosting the web application. Instances of this web application are available at different domains, and

1条回答
  •  一向
    一向 (楼主)
    2021-02-13 18:12

    Very nice and detailled question.

    You have quite certainly hit a bug, or at least an undocumented rewriteRule domain. Documentation states that:

    • The rewrite engine may be used in .htaccess files and in sections, with some additional complexity.
    • To enable the rewrite engine in this context, you need to set "RewriteEngine On" and "Options FollowSymLinks" must be enabled. If your administrator has disabled override of FollowSymLinks for a user's directory, then you cannot use the rewrite engine. This restriction is required for security reasons.
    • When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the RewriteRule pattern matching and automatically added after any relative (not starting with a slash or protocol name) substitution encounters the end of a rule set. See the RewriteBase directive for more information regarding what prefix will be added back to relative substutions.

    So no mention of the fact instruction with wildcards won't be able to strip the per-directory prefix. And playing with RewriteBase won't help you, it's done to rebuild final Url not alter the perdir work.

    But as you can see on the start there's the "with some additional complexity" sentence. Directory manipulations done by mod-rewrite are slower and more complex than general out-of-directory RewriteRules. This is stated as well in this documentation, mainly because of the perdir strip manipulation. And this means you can also write your rewriteRule out of the section, in your VirtualHost.

    • it will be faster
    • it will not be hit by this bug
    • it may have some side effects if some non-existing files should'nt be mapped to your index.php?q=$1 rule in some other directories. But I'm quite sure this is not a problem in your case.

    So simply write (without the wildcard directory):

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !=/favicon.ico
    RewriteCond %{REQUEST_URI} !=/robots.txt
    RewriteRule ^(.+)$ /index.php?q=$1 [L,QSA]
    

    And it should work, let me known if this leads to new problems.

    Edit:

    Ok, forogot the fact REQUEST_FILENAME is not yet complelty defined in VirtualHost context, it's documented, it's 'normal', when the condition is applied the file search on the real path is not done yet, this is why you must add the document root. So in fact your final solution should be :

    RewriteEngine on
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !=/favicon.ico
    RewriteCond %{REQUEST_URI} !=/robots.txt
    RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]
    

    I tried a second one, avoiding DOCUMENT_ROOT, by using late evaluation of REQUEST_FILENAME ( %{LA-U:REQUEST_FILENAME} contains the final path, which is in fact the full path to index.php in case of non existent files), but the only way I got it working is by adding a second Rule and a Or condition in the second, less simple, so the first solution is certainly better (KISS).

      RewriteCond %{LA-U:REQUEST_FILENAME} !-f [OR]
      RewriteCond %{LA-U:REQUEST_FILENAME} !/index.php
      RewriteCond %{LA-U:REQUEST_FILENAME} !-d
      RewriteCond %{REQUEST_URI} !=/favicon.ico
      RewriteCond %{REQUEST_URI} !=/robots.txt
      RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]
    
      RewriteCond %{LA-U:REQUEST_FILENAME} /index.php
      RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]
    

    0 讨论(0)
提交回复
热议问题