When user visits:
/profile.php?mode=viewprofile&u=[NUMBER FROM 1 TO 4000]
I want nginx to return:
/memberlist.php?mode=viewprofile&u=[SAME NUMBER]
How can I do it? Thank you for help.
The problem is that you need to match /profile.php and mode=viewprofile which is not trivial nginx. There are a number of ways to achieve it.
You could replicate the location ~\.php$ block and add the conditional redirection there:
location = /profile.php {
if ($arg_mode = viewprofile) {
return 301 /memberlist.php?$args;
}
... # add location ~\.php$ stuff here
}
Alternatively, check the $request_uri (which contains the original URI including query string), early in the server block:
if ($request_uri ~ "^/profile\.php\?mode=viewprofile&") {
return 301 /memberlist.php?$args;
}
See this caution on the use of the if statement.
Related
In Nginx I need to proxy pass some of the request made to the homepage.
Specificaly, I need to proxy pass them in case of URLs like:
example.com
example.com/
example.com/?anyTypeOfParameterButNotP
However, when the request contains ?p= parameter in the URL, I would like to handle it the regular way (as if there wasn't any proxy_pass at all).
So, the URLs I would like not to proxy pass would be:
example.com/?p=1234
example.com/?p=1234&foo=bar
How can I achieve that?
I've tried some if statements, some variables solutions, but I didn't figure out any way to work it out.
If you are using something that can end with "break;"
location / {
if ($query_string ~ p=) {
## regular way - try_file? and end with "break;"
}
proxy_pass http://somwhere;
}
--- or here is an if-else condition for unusual cases
location / {
set $skip_proxy 0;
if ($query_string ~ p=) {
set $skip_proxy 1;
}
if ($skip_proxy = 1) {
# when query does contain ?p=
}
if ($skip_proxy = 0) {
# when query does NOT contain ?p=
# proxy_pass http://somwhere; ?
}
}
I have two URLs with single parameter and a combination of two. They should be redirected with 301, but redirects must affect only pathes, but maintain same parameters/parameter combinations):
https://example.com/a?x=y → https://example.com/b/c?x=y
https://example.com/a?x=y&z=0 → https://example.com/d?x=y&z=0
I've tried to workout both cases with
location ~ ^/a/?(.*) {
^/b/c$1$is_args$args permanent;
}
and
location ~ ^/a/?(.*) {
^/d/$1$is_args$args permanent;
}
but it seems to be wrong approach.
location ~ ^/a(/.*$|$) # capture group $1 will not have any parameters/args!
{
return 303 $scheme://$server_name/b/c$1$is_args$args;
}
and
location ~ ^/a(/.*$|$) # in fact, location will never "see" parameters/args!
{
return 303 $scheme://$server_name/d$1$is_args$args;
}
$ at end of regex will you give trailing "uri path" (after /a and before questionmark ?) in your capture group $1.
Untested.
OK, now I understand your question. LOL. Gimmi a sec.
I know if is evil. But I think I need it.
location ~ ^/a(/.*$|$)
{
set $target_uri '/b/c';
set $change_target_uri '';
if ($arg_x) # you can't have `and` in Nginx `if` condition!
{
set $change_target_uri "${change_target_uri}_x";
}
if ($arg_y) # so use variable $change_target_uri as a workaround:
{
set $change_target_uri "${change_target_uri}_y";
}
if ($change_target_uri = '_x_y')
{
set $target_uri '/d';
}
return 303 $scheme://$server_name$target_uri$1$is_args$args;
}
Check with curl -IL https://example.com/a/blah?x=y&z=0 and look for 303 and Location:.
Untested.
Another method comes to mind.
location ~ ^/a(?<blubbi>/.*$|$)
{
if ($args ~* 'x=[^&]*(?:&[^z]|&$|$)')
{
return 303 $scheme://$server_name/b/c$blubbi?x=$arg_x;
}
if ($args ~* 'x=[^&]*&z=[^&]*')
{
return 303 $scheme://$server_name/d$blubbi?x=$arg_x&y=$arg_y;
}
}
Use only when order of parameters is fixed.
Untested.
In general regarding Nginx and Regex:
I like named variables (see blubbi). So no mixup with $1 in different scopes (http, server, location, deeper location, if, ...).
[^a]+ will match all characters except of a.
So [^&]* will make sure that you get the whole argument but not more.
Need to redirect a url with variable to another domain name. The following code works when it matches but fails when it does not match.
For example it works when the request is https://old.example.com/test/place?id=2
Fails when the request is for https://old.example.com/test/place?id=1
Need https://old.example.com/test/place?id=1 to just pass through and only catch id=2.
What is missing in the configuration? What did I miss?
location = /test/place {
if ($request_uri ~ ^/test/place\?id=2) {
return 301 https://new.example.com/test/place?id=2;
}
}
Found the solution with the help from the nginx mailing list member, Patrick. Here is the link to the conversation.
The mailing list link to the solution
The final solution is as follows.
if ( $request_uri = "/test/place?id=2" ) {
rewrite ^ https://new.example.com${uri}?${args}? last;
}
For example I need to redirect urls that match this pattern and keep the rest.
aaa.mydomain.com/path/1/listing
to
bbb.somedomain.com/path/1/listing
The "1" in that path can be any integer and needs to go to the correct redirect. Can this be done with a location block or do i need rewrite?
You can do it like this
server {
server_name aaa.mydomain.com;
return 301 //bbb.somedomain.com$request_uri;
}
UPDATE
Well, then use something like this
location ~ /path/[^/]+/listing$ {
return 301 https://bbb.somedomain.com$request_uri;
}
I would like to block a specific URL from being access and return a 444 Error.
Example:
if ( $request_uri ~ https://subdomain.domain.com/abc/xyzdirector/login.do ) {
return 444;
}
Now this works fine, the issue is if I type the following URL in my browser and change ANY of the capitalization in the sub-directories, it does not work:
Example:
https://subdomain.domain.com/ABC/xyzdirector/login.d
https://subdomain.domain.com/abc/XYZdirector/login.d
https://subdomain.domain.com/abc/xyzdirecTOR/login.d
https://subdomain.domain.com/Abc/XyzDirector/login.d
When I do this, the url gets forwarded and servered.
How do I block this?
You want a case-insensitive regex location:
location ~* ^/abc/xyzdirector/login\.do$ {
return 444;
}
If you have any other regex locations in your config, make sure you put this one above any others that may match this url.