I'm trying to get a rewrite rule working and I've discovered that if the URL begins with a question mark, Nginx fails to return 404 error as expected. Instead, index.html as defined in the root directive is served for all urls beginning with "?". (e.g. example.com/?page-does-not-exist
works for the home page but should not)
This is making it impossible to get a redirect from example.com/?format=feed&type=rss
-> example.com/rss.xml
working. This is for a blog migrated from Joomla to Jekyll.
Put simply, visiting example.com/123 returns a 404, and visiting example.com/?123 does not. The latter returns the site's home page at the URL example.com?/123. (There is no file or folder '123', so requests for it should always fail.)
Everything works perfectly with the site, including the HTTPS redirect, except for the expected 404 redirects not happening for URLs starting with a question mark. How do I fix this?
Here's my configuration:
server {
server_name example.com;
root /var/www/example.com;
index index.html;
listen 443;
ssl on;
...
rewrite "/?format=feed&type=rss" https://example.com/rss.xml permanent;
location ~* \.(?:ico|css|js|gif|jpeg|jpg|png|txt|svg|eot|woff|ttf)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
add_header Access-Control-Allow-Origin *;
valid_referers none blocked example.com;
if ($invalid_referer) {
return 403;
}
}
}
# HTTP --> HTTPS
server {
listen 80;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
The question mark signifies the end of the path portion of the uri and the beginning of the query string. Hence why nginx will not return 404 based on the portion after the question mark; the requested resource does exist and the query string parameters are just passed to it.
Regarding the other part of the question, I believe that nginx's rewrite statement does not actually match against the query string portion of the uri.
You should however be able to do something along the lines of:
NGinx
interprets everything that follows a?
as a query string, not as a path.It will only return a 404 for a non-existing path, not for a query string.
eg :
example.com/123
: if path/123
exists and if there is an index file for this path then it's OK, else it will return a 404example.com/?123
: if there is an index file in the root directory forexample.com
then it's OK. It does not check if directory?123
exists as it does not consider this as a path but as a query string.