3

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:

filename.asp?id=123&a=something.html

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?

2
  • 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, 2011 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. Jun 2, 2011 at 20:40

3 Answers 3

4

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

1

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 http://httpd.apache.org/docs/current/en/mod/mod_rewrite.html#rewriterule). 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.

0

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 site.com/index.php?blabla=haha.

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

<?php

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .