apache.htaccessmod-rewritefilenamesurlencode

Replace question mark in URL using .htaccess


I have some files that exist under a directory and its name contains a question mark.

I'm trying to replace the ? with %3F (URL encoded ?) but I get a "404 Not Found" response. Numbers in the URL are dynamic.

What I have:

https://www.example.com/uploads/10015015?afe/filename.doc

What I need:

https://www.example.com/uploads/10015015%3Fafe/filename.doc

This is the rule I added in .htaccess but it doesn't work:

RewriteCond %{QUERY_STRING} ^?afe([^&]*)
RewriteRule (.*) /$1%3F%{QUERY_STRING}? [L]

Solution

  • RewriteCond %{QUERY_STRING} ^?afe([^&]*)
    RewriteCond %{QUERY_STRING} !=""
    RewriteRule (.*) /$1%3F%{QUERY_STRING}? [L]
    

    The QUERY_STRING server variable does not contain the ? itself (query string delimiter). However, the regex ^?afe([^&]*) is entirely invalid (the ? is a regex quantifier and ^ is not quantifiable) so this would/should result in a 500 Internal Server Error since the regex cannot be compiled. (Although you say you are getting a 404, so is this rule even being processed?!)

    There's no need to check that the query string is not empty (second condition) when you have already established that there is a query string that matches the pattern (in the first condition).

    Try the following instead:

    RewriteCond %{QUERY_STRING} ^afe/[^&]+\.doc$
    RewriteRule ^(uploads/.+) $1\%3F%{QUERY_STRING} [NE,QSD,L]
    

    Note that the % before 3 must be backslash-escaped to avoid it being treated as a numeric backreference (which would otherwise be empty).

    I removed the slash prefix on the substitution string so it would be treated as a relative file-path, as opposed to a URL-path (unless you have a RewriteBase directive set).

    The QSD (Query String Discard) flag is the preferred way to discard the original query string from the request on Apache 2.4, rather than appending an empty query string (trailing ?) which would have been required on earlier versions of Apache.