Search code examples
apache.htaccessmod-rewrite

Mod rewrite. B flag doesn't work with spaces. AH10411: Rewritten query string contains control characters or spaces


After apache update, my server started dropping this error in URL queries, containing spaces:

AH10411: Rewritten query string contains control characters or spaces

URL looks as follows:

www.example.com/modulename/searchfuncname/filter,searchstring,quick fox jumps/

.htaccess as follows:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?QueryString=%{REQUEST_URI} [B,L]
</IfModule>

I tried adding B flag, removing B flag, adding BNP flag and combinations of both or none.

Nothing helped. With any URL provided, server drops the very same error.

When I try to manually replace spaces with %20: www.example.com/modulename/searchfuncname/filter,searchstring,quick%20fox%20jumps/ server replaces them back, gives 403 responce and drops AH10411 error.

But for some reason, if I replace space with + sign, server works. Disregarding BPN flag.

I tried all the variants, described in this thread: AH10411 error: Managing spaces and %20 in apache mod_rewrite none worked.


Solution

  • RewriteRule ^(.+)$ index.php?QueryString=%{REQUEST_URI} [B,L]
    

    The B flag doesn't work here because you are not using a backreference (you are using the REQUEST_URI server variable instead). Try the following instead:

    RewriteRule ^(.+)$ index.php?QueryString=/$1 [B,L]
    

    When I try to manually replace spaces with "%20": /modulename/searchfuncname/filter,searchstring,quick%20fox%20jumps/ server replaces them back

    This would make no difference, because this is identical to the first request. If you don't explicitly URL-encode the spaces in the initial request, the browser does this for you (when it makes the request) - in order to make a valid URL. (Look at the network traffic in the browser - you will see %20 regardless of whether you have manually encoded the space or not).

    But yes, the RewriteRule pattern matches the URL-decoded URL-path anyway.

    But for some reason, if I replace space with "+" sign, server works. Disregarding BPN flag.

    %20 is a URL-encoded space, regardless of where it is used in the URL. However, a + in the URL-path is a literal + (plus). But, a + in the query string is a URL-encoded space (alternative encoding). So, yes, if you used + in the URL-path of the original request then it "bypasses" this problem. The BNP flag does not apply, since it is not encoding a space, it is simply copying a literal +.


    UPDATE: Limit what is encoded

    $_GET now doesn't break into array if URL is provided with addditional parameters like /fox/&tail=red

    Probably because the & is being URL-encoded in the resulting query string. You can limit the encoding to spaces and ? only (requires Apache 2.4.26+). For example:

    RewriteRule ^(.+)$ index.php?QueryString=/$1 "[B= ?,L]"
    

    & will no longer be encoded in the backreference, so its special meaning in the query string will still apply.

    NB: You can't encode only spaces (since spaces can't be used as the last character), hence the additional ? character. Consequently, the flags argument needs to be surrounded in double quotes.