What does this apache rewrite means? - apache

RewriteCond %{QUERY_STRING} (.*)\?mem=stats$
RewriteRule ^/(.*)$ http://X.X.X.X/$1?%1 [P,L]
If the request is /asdf?mem=stats, will it rewrite to /asdf?mem=stats?asdf ?
since $1 is asdf?mem=stats and %1 is asdf ???

The %{QUERY_STRING} variable contains the query string without the leading ? (or anything before it), so %1 will never contain part of the request before query string.
If you enable mod_rewrite logging by adding LogLevel rewrite:trace6 to your VirtualHost configuration, you will see this for your RewriteCond and /asdf?mem=stats request:
... RewriteCond: input='mem=stats' pattern='(.*)\\?mem=stats$' => not-matched
Also, in your RewriteRule, pattern will be matched against the part of the URL after the hostname and port, and before the query string. Therefore $1will, even on wildcard match, not contain the query string part of the request. You can see that in log as:
... applying pattern '^/(.*)$' to uri '/asdf'

Related

I want to remove a string with a question mark at the end of my URL with .htaccess

I want to remove the string
?mobile=1
out from different URLs with .htaccess. So:
https://www.example.com/?mobile=1 should become https://www.example.com/
and
https://www.example.com/something/?mobile=1 should become https://www.example.com/something/
I tried the following
RewriteEngine On
RewriteRule ^(.+)?mobile=1 /$1 [R=301,L,NC]
But that does not seem to work. Any ideas?
RewriteRule ^(.+)?mobile=1 /$1 [R=301,L,NC]
The RewriteRule pattern matches against the URL-path only, which notably excludes the query string. So the above would never match. (Unless there was a %-encoded ? in the URL-path, eg. %3F)
To match the query string you need an additional condition (RewriteCond directive) and match against the QUERY_STRING server variable.
The regex .+ (1 or more) will not match the document root (ie. your first example: https://www.example.com/?mobile=1). You need to allow for an empty URL-path in this case. eg. .* (0 or more).
For example, try the following near the top of your root .htaccess file:
RewriteCond %{QUERY_STRING} =mobile=1
RewriteRule (.*) /$1 [QSD,R=301,L]
This matches the query string mobile=1 exactly, case-sensitive (as in your examples). No other URL parameters can exist. The = prefix on the CondPattern makes this an exact match string comparison, rather than a regex as it normally would.
And redirects to the same URL-path, represented by the $1 backreference in the substitution string that contains the URL-path from the captured group in the RewriteRule pattern.
The QSD (Query String Discard) flag removes the query string from the redirect response.
Test first with a 302 (temporary) redirect and and only change to a 301 (permanent) - if that is the intention - once you have confirmed this works as intended. 301s are cached persistently by the browser so can make testing problematic.

htaccess - cut out the question mark if there is one at the end

There is such a code
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{QUERY_STRING} !(^|&)srp=
RewriteCond %{QUERY_STRING} !(^|&)q=
RewriteRule ^(.+?)\.html$ https://%{HTTP_HOST}/$1.html? [L,R=301]
</IfModule>
<IfModule mod_rewrite.c>
RewriteRule ^(.+?)\.html(?!/amp/).+$ https://%{HTTP_HOST}/$1.html? [L,R=301]
</IfModule>
It works perfectly, but if the link is like this:
website.com/post.html?
In this case, the question mark remains. How can I delete it in this case?
You can't simply check for an empty query string since the QUERY_STRING server variable is defined and empty regardless of whether the trailing ? is present or not.
To remove a stray ? at the end of the URL-path (essentially an empty query string) you can check against THE_REQUEST server variable. For example:
RewriteCond %{THE_REQUEST} \s[^?]*\?\s
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [QSD,L,R=301]
The QSD (Query String Discard) flag removes the query string. This is the preferred way to remove the query string on Apache 2.4, as opposed to appending a ? to the substitution string.
THE_REQUEST contains the first line of the HTTP request headers and contains a string of the form:
GET /post.html? HTTP/1.1
So, the regex \s[^?]*\?\s matches a literal ? followed by a space at the end of the URL-path (avoiding a ? that could occur at the end of a non-empty query string). For example:
/post.html? redirected to /post.html
/post.html?foo=1? - no redirect, since the final ? is part of the foo URL parameter value.
Aside: You shouldn't surround each block in <IfModule mod_rewrite.c> wrapper unless the directives are optional. (And even then the directives should be grouped together.)

apache rewrite rule with query parameters

I need to redirect a existing url with three dynamic parameters values.
My existing url is like :
http://localmach.test.it:90/aa/nonLoggedUser.portal?appb=true&event=AppEvent&Code=1.564&mobile=789754654&locale=en
Now I want to redirect it to different ip with same parameters like :
http://17.22.11:90/aa/mycare?appb=true&event=AppEvent&Code=1.564&mobile=789754654&locale=en
I'm using apache url redirect in httpd.conf file.
I'm able to redirect url without parameters, but fail to redirect with parameters present.
I have tried below rewrite in httpd.conf but its not working
<VirtualHost *:90>
ServerName localmach.test.it
RewriteEngine on
RewriteCond %{QUERY_STRING} ^Code=([0-9]*)&mobile=([0-9]*)&locale=([a-z]*)$
RewriteRule ^/(.*)(aa/nonLoggedUser.portal?appb=true&event=AppEvent&)(.*)$ http://17.22.11:90/aa/mycare?appb=true&event=AppEvent&Code=%1&mobile=%2&locale=%3$
</VirtualHost>
Please help
Thanks in advance.
Parameter Code is not the first one in query string so ^ before it won't match
You cannot match query string in RewriteRule pattern.
Also regex for matching query parameters is also not correct.
You cannot use regex in target URI so $ is treated a literal $ there.
You can use this refactored rule:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)(Code=[^&]*&mobile=[^&]*&locale=[^&]*)(?:&|$) [NC]
RewriteRule ^/?aa/nonLoggedUser\.portal$ http://17.22.11:90/aa/mycare?appb=true&event=AppEvent&%1 [L,NC,NE,R=301]

How can I proxy a query string URL in Apache?

I'm trying to get an older Apache (2.2.17) to proxy:
http://foo.com/proxy/?url=http%3A%2F%2Fbar.com%2foo
to:
http://bar.com/foo
I have:
RewriteCond %{QUERY_STRING} ^url=(.*)$
RewriteRule ^/proxy/ %1? [P,L]
Unfortunately, this results in Apache trying to proxy the URL-encoded value (log output) :
(3) applying pattern '^/proxy/' to uri '/proxy/'
(4) RewriteCond: input='url='http%3A%2F%2Fbar.com%2foo'' pattern='^url=(.*)$' => matched
(2) rewrite '/proxy/' -> ''http%3A%2F%2Fbar.com%2foo'?'
(3) split uri='http%3A%2F%2Fbar.com%2foo'? -> uri='http%3A%2F%2Fbar.com%2foo', args=
(2) forcing proxy-throughput with http://foo.com/'http%3A%2F%2Fbar.com%2foo'
(1) go-ahead with proxy request proxy:http://foo.com/'http%3A%2F%2Fbar.com%2foo' [OK]
So, it appears there are two problems. One is that there are apostrophes in the result and the other is that the result is not URL decoded. I assume the reason Apache is prepending the original protocol://host is that it doesn't see the result as an URL.
If you have access to vhost/server config (and it looks like you do), you can configure one of apache's built in rewrite maps to unescape for you:
RewriteMap unescape int:unescape
Then you can use the map in your rules:
RewriteCond %{QUERY_STRING} ^url=(.*)$
RewriteRule ^/proxy/ ${unescape:%1}? [P,L]

How to do a htaccess rewrite with a question mark ? in the original url

I've got to redirect a URL that has a question mark in it, and I just can't figure out the proper .htaccess code to make it happen.
Example:
redirect 301 /home.php?cat=16 http://www.example.com/furniture.html
I believe I need to do a rewrite condition, but I'm no htaccess expert.
With the Redirect directive from mod_alias you can only examine the URI path and not the query (applies to all directives of mod_alias). If you want to examine the URI query you need to use mod_rewrite:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^cat=16$
RewriteRule ^home\.php$ http://www.example.com/furniture.html? [L,R=301]
The empty query in the replacement will prevent that the original query is being appended to the new URI.
From the apache2 mod_rewrite docs:
What is matched?
The Pattern will initially be matched
against the part of the URL after the
hostname and port, and before the
query string. 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.
for more complex parameters (like site.com/index.php?blaa=1&id=33 )
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} blaa=1&id=33
RewriteRule ^(.*)$ http://www.site.com/yourpage.html? [R=301,L]
</IfModule>