Mod Rewrite: Handling two Get Variables - apache

How can I edit this url rewrite to include a further get variable being appended to the URL? I have tried a few attemps but I always get a 500 internal server error!
I have added comments to show what I am trying to achieve.
# /view.php?user=h5k6&page=1 externally to /h5k6/1
# Some times the page get variable will not exist so it should just show /h5k6
RewriteCond %{THE_REQUEST} ^GET\ /view\.php
RewriteCond %{QUERY_STRING} ^([^&]*&)*user=([^&]+)&?.*$
RewriteRule ^view\.php$ /%2? [L,R=301]
# /h5k6/1 internally to /view.php?t=h5k6&page=1
RewriteRule ^([0-9a-z]+)$ view.php?t=$1 [L]
Thanks all for any help

The problem with URI query arguments is that they may appear in any order. With two arguments you just have two permutations (A before B and B before A). But the more arguments you want to extract the more permutations you have (n!).
That means you should put the arguments in the right order so that you can them at a time:
RewriteCond %{THE_REQUEST} ^GET\ /view\.php
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)(page=[^&]+)&?([^&].*)?$
RewriteCond %3&%1%4 ^(([^&]*&)*)(user=[^&]+)&?([^&].*)?$
RewriteCond %3&%1%4 ^user=([^&]+)&page=([^&]+)&?([^&].*)?$
RewriteRule ^view\.php$ /%1/%2?%3 [L,R=301]
The first condition checks the request line like in your rule. The second condition picks the page argument and puts it at the start of the query string. The third condition does the same with the user argument so that the order always is: first user, second page. Then we use the fourth condition to take both argument values at a time to use them in the RewriteRule replacement. The rest of the query is appended to the replacement URI (see %3) but you can leave that off if you want.
As you see, the more arguments you want to extract, the more complex it gets. And it is easier to do that with a language that is more powerful than mod_rewrite like PHP.

Related

How to redirect URL using .htaccess with dynamic parameter?

I want to redirect
https://example.com/product-info/A100001
to
https://example.com/product-info/index/index/id/A100001
using htaccess redirect rule
A100001 will be dynamic like
A100001
A100002
A100003
A100004
....
I am trying this
RewriteEngine on
RewriteCond %{QUERY_STRING} product-info/A100001
RewriteRule ^$ /routing/index/index/id/? [L,R=301]
Source
Also tried other example but not working in my scnario
Anyone who expert in htacees rules can help me in this.
RewriteCond %{QUERY_STRING} product-info/A100001
RewriteRule ^$ /routing/index/index/id/? [L,R=301]
Your example URL contains a URL-path only, it does not contain a query string. The rule you've posted would redirect /?product-info/A100001 to /routing/index/index/id/.
Try something like the following instead:
RewriteRule ^(product-info)/(A\d{6})$ /$1/index/index/id/$2 [R=302,L]
The above would redirect a request of the form /product-info/A123456 to /product-info/index/index/id/A123456.
The $1 backreference simply contains product-info, captured from the RewriteRule pattern (saves repitition) and $2 contains the dynamic part (an A followed by 6 digits).
This is a 302 (temporary) redirect. Always test first with a 302 to avoid potential caching issues.
The order of directives in your .htaccess file is important. This rule will likely need to go near the top of the file, before any existing rewrites.
UPDATE:
redirection is working with your code, Can you please let me know the parameter pattern, I need the number from A452218 to A572217
Regex does not handle numeric ranges, only character ranges. If you specifically only want to match numbers in the stated range then you would need to do something (more complex) like this:
RewriteRule ^(product-info)/A(45221[89]|4522[2-9]\d|452[3-9]\d{2}|45[3-9]\d{3}|4[6-9]\d{4}|5[0-6]\d{4}|57[01]\d{3}|572[01]\d{2}|57220\d|57221[0-7])$ /$1/index/index/id/A$2 [R=302,L]
NB: The $2 backreference now only contains the dynamic number, less the A prefix, which is now explicitly included in the substitution string.

Can't pass parameters to another redirect website

I want to redirect to another website, and pass the parameters also.
Example: I go to my website: source.example/?code=12345
Then, I want it to redirect to target.example/?code=12345.
I am currently using this for my .htaccess file, since I figured out from other posts that if I query a certain parameter, it will get passed also:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^code=[NS]$
RewriteRule "www.google.com" /$1 [R=302,L]
Also, I tried many different approaches looking at these stack questions:
simple .htaccess redirect : how to redirect with parameters?
Redirect and keep the parameter in the url on .htaccess
But I can't get it running :(
since I figured out from other posts that if I query a certain parameter, it will get passed also
This is not true. The query string is passed through by default - there is nothing extra you need to do if you want the same query string on the target URL.
RewriteCond %{QUERY_STRING} ^code=[NS]$
RewriteRule "www.google.com" /$1 [R=302,L]
This code won't match the source URL for many reasons:
"www.google.com" - The first argument to the RewriteRule directive is a regex that matches the source URL-path (less the slash prefix). In your example the URL-path is empty.
^code=[NS]$ matches either code=N or code=S - which is not the intention from your example. (The [NS] looks like a mangled RewriteRule flag?!)
/$1 - this is the substitition string, ie. the URL you want to redirect to. (The $1 backreference is always empty, so this is meaningless.)
To redirect from source.example/?code=<number> to https://target.example/?code=<number> then try the following instead:
RewriteCond %{HTTP_HOST} ^source\.example [NC]
RewriteCond %{QUERY_STRING} ^code=\d+$
RewriteRule ^$ https://target.example/ [R=302,L]
This only matches a query string of the form code=1234. It does not match code= or code=1234&foo=bar, etc.
The query string is passed through by default.
If source.example is the only domain being hosted at the current location then you can remove the first condition that explicitly checks the requested hostname.
The order of directives in the .htaccess file is important. An external redirect like this should go near the top.

How I can rewrite a query-string based URL only partially

I want to rewrite the following URL, based on part of its query string, but at the same time, I want to keep the rest of the Query String.
Original URL:
http://example.com/index.php?route=product/show&item_id=25&show_mobile=true
To be converted to:
http://example.com/product/show/?item_id=25&show_mobile=true
I have searched and found the following wiki on Apache:
https://wiki.apache.org/httpd/RewriteQueryString
But it hasn't a section for rewriting a single Key&Value pair in Query string and keeping the rest.
This should get you close, it's based on the "remove a key" entry from the wiki. You want to isolate the part that will go into the path in the first capture and use the 2nd capture for the remaining query string.
RewriteCond %{QUERY_STRING} ^(route=[^&]*)&(.*)
RewriteRule ^index.php /%1?%2
You can use this generic rule to capture parameter value of route in any order from query string and reuse in target URL:
RewriteEngine On
RewriteCond %{THE_REQUEST} \?(.*&)?route=([^&]*)&?(\S*)\sHTTP [NC]
RewriteRule ^index\.php$ /%2?%1%3 [R=301,NE,L]

Add parameter using htaccess on condition

This will be a simple for those familiar with Apache rules.
Situation
Using Alipay for a payment platform, the return URL cannot feature any of your own URL parameters (be it GET or POST). However, I am using Joomla and specifically Akeeba subscriptions. This component expects a parameter in the URL in accordance with the payment platform in question.
I want to detect (through one of Alipay's URL parameters) when a return page is hit and add the extra parameter.
Example (domain and page redacted)
http://...?
currency=HKD&
total_fee=2.00&
out_trade_no=211&
trade_no=2014040100276615&
trade_status=TRADE_FINISHED
Desired outcome
http://...?
currency=HKD&
total_fee=2.00&
out_trade_no=211&
trade_no=2014040100276615&
trade_status=TRADE_FINISHED&
paymentmethod=alipay
The simple addition of a &paymentmethod=alipay
Problem
I can't seem to get Apache to pick up the rule; here are a couple of attempts so far. Please note, I definitely can use .htaccess and don't need to change RewriteBase.
-- Attempt 1 --
RewriteCond %{QUERY_STRING} out_trade_no=
RewriteRule ^out_trade_no paymentmethod=alipay&out_trade_no [R,L,QSA]
-- Attempt 2 --
RewriteCond %{QUERY_STRING} (^|&)out_trade_no=(&|$) [NC]
RewriteRule ^ %{REQUEST_URI}&paymentmethod=alipay [L,R=301,QSA]
Progress
Combining the two, I have made progress but, now seem to have the Rewrite part spamming "paymentmethod=alipay" which seems to cause an error.
RewriteCond %{QUERY_STRING} out_trade_no=
RewriteCond %{QUERY_STRING} !paymentmethod=
RewriteRule ^ %{REQUEST_URI}&paymentmethod=alipay [R,L]
Now getting a redirect chain until it automatically stops at a redirect limit
If you are just trying to match a query string from that URL with that rewritecond you need to match the first one(currency). Which is the easiest.
Try this. It will send all the parameters you want.
RewriteCond %{QUERY_STRING} ^\bcurrency=
RewriteRule ^(.*)$ /$1?paymentmethod=alipay [R,QSA,L]

.htaccess how to force/automatic clean URL

I'm new to mod_rewrite but am trying my best to fix up my site with clean URLs.
Using RewriteRule I can get it so you can type in a clean URl and get to the right page, but what I'm having trouble with is automatically redirecting to the clean URL if a "messy" one is used (which is highly possible due to user submitted links and content etc)
Now, I have this bit of code which I found on another .htaccess forum, and it works in one situation, but not another. I'll explain:
# FORCE CLEAN URLS
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php\?(.*)=([^\s]+) [NC]
RewriteRule ^ %1\/%2? [R=301,L]
This works fine on an address like this, for example: www.domain.com/index.php?cmd=login it automatically redirects to www.domain.com/cmd/login
But the problem comes when there is more than one query, like: www.domain.com/index.php?cmd=view-profile&user=bob
I can't figure out how to make it sort out that kind of URL when there could be up to 3 or more queries in the address.
I'm not fully competent with regex, so my attempts to amend the code snippet I have has failed thus far.
Any help would be appreciated! I would like them to be 301 redirects so that the site can get indexed properly and be SEO compliant no matter what type of clean or messy URL is used, but I'm open to suggestions!
EDIT
After playing around with the regex for a few hours, I've progressed but got stumped again.
If I make the expression to this:
index\.php\?(.*)=([^\s]+)(&(.*)=([^\s]+))?+
$1/$2/$3/$4/$5
It will match these 3 URLs from index.php onwards:
http://site.com/index.php?cmd=shop&cat=78
http://site.com/index.php?cmd=shop
http://site.com/index.php?cmd=shop&cat=78&product=68
BUT the resulted output varies depending on which it is. These are my results:
http://site.com/cmd=shop&cat/78///
http://site.com/cmd/shop///
http://site.com/cmd=shop&cat=78&product/68///
I'm nit sure how to get it to treat certain parts as optional so it groups properly.
You'll need to deal with each number of pairs of parameters separately. The one you have can be used to handle one name/value pair, then approach it similarly for 2, and 3 (and 4 if needed):
# To handle a single name/value pair in the query string:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php\?([^&=]+)=([^&\ ]+)(\ |$) [NC]
RewriteRule ^ /%1\/%2? [R=301,L]
# To handle 2:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php\?([^&=]+)=([^&\ ]+)&([^&=]+)=([^&\ ]+)(\ |$) [NC]
RewriteRule ^ /%1\/%2/%3/%4? [R=301,L]
# To handle 3:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php\?([^&=]+)=([^&\ ]+)&([^&=]+)=([^&\ ]+)&([^&=]+)=([^&\ ]+)(\ |$) [NC]
RewriteRule ^ /%1\/%2/%3/%4/%5/%6? [R=301,L]
Basically, you're adding another &([^&=]+)=([^&\ ]+) before the check for the end of the request, (\ |$), and adding another /%#/%# to the end of the target URI, where the #'s are appropriate incremented backreferences.