A .htaccess redirect while editing the query string

Viewed 89

I am trying to redirect to a new domain, while keeping the query string but in a modified way.

For example, I want to redirect:

http://guides.freshstoreinstant.com/fresh-store-instant/how-to-find-your-amazon-affiliate-key-secret-key

to

https://guides.freshlabs.group/search?query=how+to+find+your+amazon+affiliate+key+secret+key

So I am wanting to:

  1. Take the last "folder" from the original URL (how-to-find-your-amazon-affiliate-key-secret-key)

  2. Replace - with +

  3. Append the result to https://guides.freshlabs.group/search?query= and redirect with 301

I tried a few things and know a little bit about .htaccess but this one has me stumped

UPDATE

This could be easier using a combination of .htaccess and PHP. Can I use .htaccess to rewrite all URLs to index.php, then use PHP to replace the characters and redirect?

2 Answers

This is not possible using apache's rewrite module it does not support such search&replace actions. It only rewrites. If you really cannot live with the unaltered string which you probably could still split in your processing logic, then you have these options:

either introduce another rewriting layer, based on some scripting engine which accepts the unaltered string, converts it by means of normal string operations and output redirection headers

or you may be able to do something with apache's substitute module, but youneed to install and load that and it's usage is not exactly easy (did that, grumbled a lot...)

or use a strange looking but working workaround:

RewriteEngine on

RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7+$8+$9 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7+$8 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1 [R=301,QSA]

This rule set will work likewise in the http servers host configuration or in a dynamic configuration file (".htaccess" style file).


UPDATE:

I realized that your example string to be converted contains more than 9 tokens which is the more or less hard coded limit of back references supported by an apache http server. You could change that if you can recompile the sources, in that case the above solution is fine and can be extended up to a number of tokens you feel safe with.

If that is not an option (as typical), you need to try something like this instead:

RewriteEngine on

RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} (^|&)query=(.+)&|$
RewriteRule ^/?fresh-store-instant/?$ https://guides.freshlabs.group/search [R=301,QSA]

RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} (^|&)query=(.+)(&|$)
RewriteRule ^/?fresh-store-instant/([^/-]*)[-]?(.*)/?$ /fresh-store-instant/$2?query=%2+$1 [N,QSD]

RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} !(^|&)query=
RewriteRule ^/?fresh-store-instant/([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1 [R=301,QSD]

RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} !(^|&)query=
RewriteRule ^/?fresh-store-instant/([^/-]*)[-](.*)/?$ /fresh-store-instant/$2?query=$1 [N,QSD]

Note: I did not test this, just wrote it down, so there might be some smaller glitch in there. It should work though. It implements a multiple rewriting strategy: it rewrites each token in a separate go, "storing" that token in a preliminary query argument. One by one the tokens are assembled until the final external redirection is performed because no more tokens to be converted are present in the request.


And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

You can do this using mod_rewrite in .htaccess. Try the following at the top of your .htaccess file:

RewriteEngine On

RewriteRule ^(fresh-store-instant)/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^fresh-store-instant/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]
  1. The first rule repeatedly rewrites the request (internally) replacing all - (hyphens) with + in the second path segment. The N (next) flag explicitly triggers the rewriting loop. This should be used with caution; as with any recursive-like behaviour, it needs to fail at some point. (NB: A + in the URL-path is simply a literal +.)

  2. Once all the hyphens have been replaced, the second rule triggers an external redirect to the other domain, copying the second path segment (now containing +) to the query string in the target URL. (NB: A + in the query string part of the URL is seen as an encoded space by the receiving server.)

Note that this is a temporary (302) redirect. Only change to a 301 (permanent) once you have confirmed it works OK - to avoid caching issues.

Clear your browser cache before testing.

...while keeping the query string but in a modified way

There is no query string on your example source URL to "keep"? Note that the above redirect overwrites any query string that might be present on the source URL. Include the QSA on the second RewriteRule if you want to "append" the query string from the request.


UPDATE:

the first "folder" can vary (e.g. http://guides.freshstoreinstant.com/fresh-store-builder/...)

If there is a limited subset of folders then it will probably be better to explicitly name each one, in order to avoid potential conflicts with other URLs on your site. For example:

RewriteRule ^(fresh-store-(?:instant|builder))/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^fresh-store-(?:instant|builder)/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]

If you make the initial directory entirely variable (such as below) then I can imagine this conflicting with existing URLs:

RewriteRule ^([\w-]+)/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^([\w-]+)/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]
Related