Handling '?' in mod_rewrite - apache

I have a page that asks a user to confirm if he wants to continue or cancel and I use a rewrite rule for it:
RewriteRule ^click/(.+)$ aclick.php?url=$1 [B]
The problem arises when the URL has a question mark. For example:
http://example.com/click/yahoo.com/mobile/?s=ladygaga
My goal is that this URL be re-written as:
http://example.com/aclick.php?url=yahoo.com/mobile/%3fs=ladygaga
So that the continue button will proceed to: 'http://yahoo.com/mobile/?s=ladygaga'
However, the continue button is just linked to 'http://yahoo.com/mobile/'.
Does anyone have an idea to fix this?

Use %{QUERY_STRING} as follows. You have to refer REDIRECT_QUERY_STRING instead of QUERY_STRING.
RewriteRule ^click/(.+) aclick.php?url=$1?%{QUERY_STRING} [B,L]
B flag will escape the string excessively. If you access http://example.com/click/yahoo.com/mobile/?s=ladygaga, the query string will be url=yahoo%2ecom%2fmobile%2f?s=ladygaga. (It does not cause bad influence.)
In case that URL have no query string, redundant "?" is added to the end of query string. To prevent this, use RewriteCond:
# If URL have any query string, then
RewriteCond %{QUERY_STRING} .
RewriteRule ^click/(.+) aclick.php?url=$1?%{QUERY_STRING} [B,L]
# otherwise,
RewriteRule ^click/(.+) aclick.php?url=$1
You can simply written as follows:
RewriteRule ^click/(.+) aclick.php
Program aclick.php can refer environment variables REQUEST_URI, REDIRECT_URL, QUERY_STRING etc.

Related

htaccess url redirect with get parameters ID and reduce value

I want to do an url redirect to a new domain by retrieving the ID parameter but only taking the first 4 characters. Anyone know how to do this?
For example, an original url:
http://www.original.example/see/news/actualite.php?newsId=be9e836&newsTitle="blablabla"
To :
https://www.new.example/actualites/be9e
I have tested :
RewriteCond %{QUERY_STRING} ^newsId=(.*)$ [NC]
RewriteRule ^$ https://www.new.example/actualites/%1? [NC,L,R]
RewriteCond %{QUERY_STRING} ^newsId=(.*)$ [NC]
RewriteRule ^$ https://www.new.example/actualites/%1? [NC,L,R]
There are a couple of problems with this:
The regex ^$ in the RewriteRule pattern only matches the document root. The URL in your example is /see/news/actualite.php - so this rule will never match (and the conditions are never processed).
The regex ^newsId=(.*)$ is capturing everything after newsId=, including any additional URL parameters. You only need the first 4 characters of this particular URL param.
As an aside, your existing condition is dependent on newsId being the first URL parameter. Maybe this is always the case, maybe not. But it is relatively trivial to check for this URL parameter, regardless of order.
Also, do you need a case-insensitive match? Or is it always newsId as stated in your example. Only use the NC flag if this is necessary, not as a default.
Try the following instead:
RewriteCond %{QUERY_STRING} (?:^|&)newsId=([^&]{4})
RewriteRule ^see/news/actualite\.php$ https://www.new.example/actualites/%1 [QSD,R,L]
The %1 backreference now contains just the first 4 characters of the newsId URL parameter value (ie. non & characters), as denoted by the regex ([^&]{4}).
The QSD flag (Apache 2.4) discards the original query string from teh redirect response. No need to append the substitution string with ? (an empty query string), as would have been required in earlier versions of Apache.
UPDATE:
I have an anchor link (#) which is added at the end of the link, is there a possibility of deleting it to make a clean link? Example, currently I have: https://www.new.example/news/4565/#title Ideally : https://www.new.example/news/4565
The "problem" here is that the browser manages the "fragment identifier" (fragid) (ie. the "anchor link (#)") and preserves this through the redirect. In other words, the browser re-appends the fragid to the redirect response from the server. The fragid is never sent to the server, so we cannot detect this server side prior to issuing the HTTP redirect.
The only thing we can do is to append an empty fragid (ie. a trailing #) in the hope that the browser discards the original fragment. Unfortunately, you will likely end up with a trailing # on your redirected URLs (browser dependent).
For example (simplified):
:
RewriteRule .... https://example.com/# [R=301,NE,L]
Note that you will need the NE flag here to prevent Apache from URL-encoding the # in the redirect response.
Like I say above, browsers might handle this differently.
Further reading:
URL Fragment and 302 redirects
redirect is keeping hash
How to clear fragment identifier on 302 redirect?

Apache Mod_Rewrite Question Mark

I need to redirect an incoming request with the following URL:
http://mywebsite.com/abc/mapserv.exe?map=123
to
http://mywebsite.com/abc/mapserv.exe?map=C:\Mapserver\ms4w\Apache\htdocs\Mapfiles\123.map
I already managed to do simple mod_rewrites but the question mark is killing this one all the time. I am not able to adapt common Query String examples to my case so I need help with this exact case.
As though you did not show your try, you could test this:
RewriteEngine On
RewriteCond %{QUERY_STRING} map=([0-9]+)$
RewriteRule . %{REQUEST_URI}?map=C:\\Mapserver\\ms4w\\Apache\\htdocs\\Mapfiles\\%1.map [NE,L]
Rewrite flags used:
NE: Not Escape,
L: Last instruction to run.
I was still having trouble with the .exe url since it is not accessible if you dont deliver the parameters right when you send the request. And then the redirect wont fire. So I made a dummy mapserver.php file which allows setting a parameter like so:
http://mywebsite.com/abc/mapserver.php?map=123
After hours of trying I ended up with the following RewriteRule:
RewriteCond %{QUERY_STRING} ^map=(.*)$
RewriteRule ^mapserver.php?$ /cgi-bin/mapserv.exe?map=C://Mapserver//ms4w//Apache//htdocs//Mapfiles//%1.map

Apache Redirection {QUERY_STRING} input is empty in Rewrite Cond

I would like to perform redirection based on QUERY_STRING parameter, for example:
from this URL
mySite.com/index.html#query?id=1111
to this URL
mySite.com/newSite/query#query?id=111
I searched online on how to use the parameter in RewriteCond, and below is my configuration:
RewriteEngine ON
RewriteCond %{QUERY_STRING} ^query?id.*$
RewriteCond %{REQUEST_URI} ^/index.html.*$
RewriteRule /index.html(.*) /newSite/query%(QUERY_STRING)
I have the trace debug mode on, and noticed that the condition got fired, but the input is empty, as showed in screen below
rewritecond input = ''
Can anyone please advise on this issue? Thank!
as far as I know (working in php), the text after the anchor (#) is never actually send to the server.
your conditions will always fire, even if there are no characters after /index.html, this is because you used a 0-or-more quantifier (the * symbol), so if there are 0 or more of any character (. symbol), it will trigger the rewrite rule
problem is that there is no actual input (as you noticed :))

Using Apache's mod rewrite how to redirect depending the query string?

Using Apache's mod rewrite how to redirect foo.php?r=ok to boo.php (that is, depending the query string: if r = ok then redirect).
you can't use query string (the string after "?" character) as variable for rewrite, because query string is not a part of URL path.
you need to modify foo.php?r=ok to some string path like "foo.php/redirect/"
From the Apache manual discussing mod_rewrite:
If you wish to match against the
hostname, port, or query string, use a
RewriteCond with the %{HTTP_HOST},
%{SERVER_PORT}, or %{QUERY_STRING}
variables respectively.
Look closely at RewriteRules and RewriteConditions
EDIT: Added a working example
The RegEx use to write these is just pure heaven </sarcasm>
Any how... here's a simple rule (Apache2, Mac OS X 10.5.8)
RewriteCond $1 ^(foo\.php)
RewriteCond %{QUERY_STRING} (r=ok)
RewriteRule (foo\.php) /bar.php [R]
I tested this for as many obvious caveats that I could think of (ie r=ko, oof.php, foo.php?r=o), but couldn't break it.

Apache mod_rewrite and PHP ?argument=something

I'm trying to get all HTML and PHP files on my site to redirect through the index.php, so that they can have common frames applied to them, a templating solution I coded that I found to be quite elegant. Anywho, I'm having issues with my PHP files, specifically those that have arguments after them.
My regular rule for PHP files is the following:
RewriteCond %{REQUEST_URI} !index.php$
RewriteRule ^(.+).php$ index.php?page=$1&type=1 [NC,L]
This works fine for any pages that have no arguments, but you can see that any PHP documents that have
?argument=something
end up as:
index.php?page=path/to/page?argument=something&type=1
which is not a working solution at all. Now, what's bothering me here is the $ at the end of the rule, shouldn't that cause it to fail if there is anything after the .php?
Anywho, I tried rewriting the rule as:
RewriteRule ^(.+).php\?(.+)$ index.php?page=$1&type=1&$2 [NC,L]
but that simply doesn't trigger at all. It seems that the regex flavor used in mod_rewrite is far different than I'm used to working with, so I'm sure these are simple mistakes I've made, but I can't seem to find decent documentation for this flavor of regex other than the most basic of examples.
Can anyone show me what I'm doing wrong? Thanks.
Try qsa in your rule, which stands for "query string append" - mod_rewrite will then append any query string from the original URL to the rewritten URL
RewriteCond %{REQUEST_URI} !index.php$
RewriteRule ^(.+).php$ index.php?page=$1&type=1 [NC,L,qsa]
RewriteRule doesn't match against the query string, which is why your second attempt did not work. Here's the relevant note from the manual
The Pattern will not be matched
against the query string. Instead, you
must use a RewriteCond with the
%{QUERY_STRING} variable. You can,
however, create URLs in the
substitution string, containing a
query string part. Simply use a
question mark inside the substitution
string, to indicate that the following
text should be re-injected into the
query string. When you want to erase
an existing query string, end the
substitution string with just a
question mark. To combine a new query
string with an old one, use the [QSA]
flag.