skip to Main Content

I try write a rewrite rule on an apache webserver configuration in the httpd.conf file, which should replace every GET parameter key which contains &foo= to &poo= but shouldn’t change any other GET parameter.
For example:

https://test.com/imb/rs/search?test=abc&foo=123&test2=def&foo=456

Should be changed to:

https://test.com/imb/rs/search?test=abc&poo=123&test2=def&poo=456

I tried it with:

RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ $1?%1?&poo=%2 [NC]

But it only changed the last occurrence of foo to poo.

My httpd.conf file is structured as follows:

<Directory ~ "^/imb/rs/*">
   Options Indexes FollowSymLinks
   AllowOverride All
   Order allow,deny
   Allow from all
   RewriteEngine on
   RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
   RewriteRule ^(.*)$ $1?%1&poo=%2 [NC]
</Directory>

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
   RewriteRule ^(.*)$ $1?%1&poo=%2 [NC]
</IfModule>

The /imb/rs/ part is written because the url starts with https://test.com/imb/rs/ and continues after that. I thought that would match my case.

Does anyone have an idea how I could solve this?

2

Answers


  1. Chosen as BEST ANSWER

    I found this solution which works only with 1 occurrence, not with multiple.

    This one takes only the first occurrence:

    RewriteCond %{QUERY_STRING} (.*?)foo(.*) [NC] 
    RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC] 
    

    This one takes only the last occurrence:

    RewriteCond %{QUERY_STRING} (.*)foo(.*) [NC] 
    RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC] 
    

    But I couldn't find a way to replace all of them.


  2. <Directory ~ "^/imb/rs/*">
       Options Indexes FollowSymLinks
       AllowOverride All
       Order allow,deny
       Allow from all
       RewriteEngine on
       RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
       RewriteRule ^(.*)$ $1?%1&poo=%2 [NC]
    </Directory>
    
    <IfModule mod_rewrite.c>
       RewriteEngine on
       RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
       RewriteRule ^(.*)$ $1?%1&poo=%2 [NC]
    </IfModule>
    

    There are a few issues here. The <Directory> container is not going to match the request, so the mod_rewrite directives inside this container are not processed. Only the mod_rewrite directives outside the <Directory> container are processed, but this will only replace the last instance of &foo= in the query string (since the regex is greedy and the rewrite engine makes just a single pass in a vHost/server context).

    <Directory ~ "^/imb/rs/*">
    

    You are mixing regex and wildcard syntax. However, this should be an absolute filesystem path, not a URL-path, as this appears to be ("url starts with https://test.com/imb/rs/"). But you do not need to use the regex version of the <Directory> directive here anyway. I’m assuming /imb/rs is a physical directory and not simply a virtual URL-path?

    AllowOverride All
    

    You are explicitly enabling .htaccess overrides. If you do have a .htaccess file that contains mod_rewrite directives in this directory then this will completely override the <Directory> container in the server config. You should probably be disabling .htaccess overrides altogether.

    Order allow,deny
    Allow from all
    

    These are Apache 2.2 directives and are formerly deprecated on Apache 2.4 (which I would assume you are using). You should be using the equivalent Require all granted instead. (But you do need to make sure you are using Apache 2.4 directives throughout – do not mix the two.)

    Options Indexes FollowSymLinks
    

    Aside: Are you intentionally allowing mod_autoindex to generate directory listings of your content? Generally, this should be disabled (ie. remove Indexes from this rule).

    Try the following instead:

    <Directory "/absolute/file/path/to/imb/rs">
       Options Indexes FollowSymLinks
       AllowOverride None
       Require all granted
    
       RewriteEngine On
       RewriteCond %{QUERY_STRING} (.*)&foo=(.*)
       RewriteRule (.*) $1?%1&poo=%2 [L]
    </Directory>
    

    And remove the rule from outside the <Directory> container.

    So, the rule you had in the beginning was basically OK. The start-of-string and end-of-string anchors are not required here, since the regex is greedy. The NC flag is not required. The L flag is not strictly required, but would be if you add any more rules later.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search