Home > Software engineering >  Apache2 mod_rewrite difficulty with GET variables
Apache2 mod_rewrite difficulty with GET variables

Time:06-06

On the website.conf file I have:

<VirtualHost *:80>
    DocumentRoot /srv/http/website/cgi-bin
    ServerName website
    ServerAlias www.website

    RewriteEngine on
    RewriteRule ^$ ""
    RewriteRule ^([a-z] )$ /?tab=repo

...

My goal is to have http://localhost/ redirect to localhost and http://localhost/word redirect to http://localhost/?tab=word. With the current directives I get a 404 error, because it's trying to open the file repo @ DocumentRoot. All I need is to rewrite the URL to make the word be a GET variable.

A directive like the following works:

RewriteRule /word$ http://localhost/?tab=word

This is obviously somewhat simplistic because I would then have to do it for every possibility.

I experimented with those directives on this website https://htaccess.madewithlove.com/, that I found from another thread on SO, the results are what I expect them to be, I.E.: http://localhost/word is transformed to http://localhost/?tab=word.

Extra info: The website does not have any PHP.

CodePudding user response:

# Virtual Host
RewriteRule ^$ ""
RewriteRule ^([a-z] )$ /?tab=repo

A directive like the following works:

RewriteRule /word$ http://localhost/?tab=word

The difference with the "working directive" is that you've included a slash prefix. The regex ^([a-z] )$ does not allow for a slash prefix, so never matches.

You are also failing to use the captured backreference (ie. $1) in the substitution string, so it would always rewrite to /?tab=repo regardless of the URL requested.

Consequently, the first rule, that matches against ^$ will never match either - but this rule is not required. You are not performing a redirect when requesting the root - you just don't want to do anything and instead allow mod_dir to serve the directory index.

In a virtualhost context the URL-path matched by the RewriteRule pattern is a root-relative URL-path, starting with a slash.

So, your rule(s) should be like this instead:

RewriteEngine On
RewriteRule ^/([a-z] )$ /?tab=$1 [L]

(Or, make the slash prefix optional, ie. ^/?([a-z] )$)

However, /?tab=<word> is not strictly a valid end-point. What is the actual file that is handling the request? This should be included in the rewrite (and not rely on the DirectoryIndex). You state you are not using PHP, so how are you reading the URL parameter?

I experimented with those directives on this website https://htaccess.madewithlove.com/,

You are not using .htaccess in your example. mod_rewrite behaves slightly differently depending on context (.htaccess, directory, virtualhost and server).


Reference:

What is matched?

In VirtualHost context, The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html"). This is the (%-decoded) URL-path.

In per-directory context (Directory and .htaccess), the Pattern is matched against only a partial path, for example a request of "/app1/index.html" may result in comparison against "app1/index.html" or "index.html" depending on where the RewriteRule is defined.

CodePudding user response:

After tinkering a bit more I got down to this:

   RewriteRule ^(.*)$ %{REQUEST_FILENAME} [PT,L] 

   RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d 
   RewriteRule ^(.*)$ %{REQUEST_FILENAME} [PT,L] 

   RewriteRule ^/([^index.cgi]{1}. )$ /index.cgi?tab=$1 [L]

It opens files if they exist and sends requests that don't exist to my C cgicc program. The only thing I don't understand is why the -d condition isn't opening directories the same way the -f one opens files.

  • Related