Sign up ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I've just taken on hosting of an ancient site that was converted from asp to static html, consisting of about 6,000 files. However, my server doesn't like the filenames, giving a 404 error. The URLs are all of the form:


where id is always an integer and a is always a string of characters & numbers.

Is there any way I can use htaccess and mod_rewrite to tell it that the question mark is part of the URL rather than signifying a query string?

share|improve this question
Using the ? to separate arguments from the URI is the default behavior. How do you have apache configured now? And does filename.asp exist in the directory you're shooting for? –  Jack M. Jun 2 '11 at 19:02
Apache is configured pretty much out of the box excerpt for performance changes. But as i've got multiple sites on the server i can't change it server-wide, so I'd be looking to do something via htaccess. –  Simon Blackbourn Jun 2 '11 at 20:40

3 Answers 3

up vote 4 down vote accepted

You probably already know you are not the first person to have this need :)

# Allow filenames containing '?' to be served by escaping the '?' in the HTTP
# request so it's not interpreted as a query string.
# Apache 2.2: set query string to empty by ending rewritten path with '?'.
# Apache 2.4: use the qsdiscard flag instead
RewriteCond %{QUERY_STRING} !=""
RewriteRule ^/(.*) /$1\%3F%{QUERY_STRING}? [noescape,last,redirect]

The key is the combination of adding a redirect and NE/noescape to ensure apache doesn't escape what we don't want escaped.

The above rule will mean that the entire site under this rewrite will treat ? as part of the filename. If you need to have it match your filename.asp - just add it to the RewriteRule

share|improve this answer

I would suggest a rewrite that directly serve the file, by escaping the "?" to "\%F3".

To serve files:

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

Do the same for folders (i.e. serve index.html - adapt index.html to fit your needs)

RewriteCond %{REQUEST_FILENAME} ^.*/$
RewriteCond %{QUERY_STRING} !=""
RewriteRule ^(.*)/$ $1/index.html\%3F%{QUERY_STRING}? [L]

First, we test if the file exists (see next paragraph about this), second we check that we have a query string (otherwise, serve the file as usual), then add the "?" and the original query string and serve it.

I add the "?" at the end, to erase the QueryString (since it is already handled), and to avoid the rule to be applied a second time (ex: if serving a file in a subdirectory). Other solution would be to use the "END" flag (see According to the same page, and as mentionned by @csharkey and @Gavin C, [qsdiscard] could be added instead in apache 2.4:

RewriteRule ^(.*)/$ $1/index.html\%3F%{QUERY_STRING}? [L,qsdiscard]

Caveat: I didn't test this solution thouroughly, so errors may remains.

share|improve this answer

I have converted an ancient Joomla site with wget --mirror. In my case all the links went through the index.php file, so all of them are something like

I have resolved the problem by adding an index.php file with the following content:


include 'index.php?' . $_SERVER['QUERY_STRING'];

This way you don't even need the rewrite module. Obviously it performs slightly worse, and maybe it's less elegant, but at least you don't have to convert link/filenames.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.