How to do location /test/place?id=2

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

How to do location /test/place?id=2

P.V.Anthony
Hi,

Currently have the following url,

https://old.example.com/test/place?id=1
https://old.example.com/test/place?id=2
https://old.example.com/test/place?id=3

Need to redirect only id=2 to another url.

Did the following and it works for id=2. Need id=1 and id=3 to continue
normally without change.

location = /test/place {
      if ($args = "id=2") {
        return 301 https://new.example.com/test/place?$args;
     }
}


Or is there a way to do the following? That would be ideal.


location = /test/place?id=2 {
     return 301 https://new.example.com/test/place?id=2
}

Unfortunately the above does not work. What is missing?

--
P.V.Anthony

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

J. Lewis Muir
On 10/18, P.V.Anthony wrote:

> Currently have the following url,
>
> https://old.example.com/test/place?id=1
> https://old.example.com/test/place?id=2
> https://old.example.com/test/place?id=3
>
> Need to redirect only id=2 to another url.
>
> Did the following and it works for id=2. Need id=1 and id=3 to continue
> normally without change.
>
> location = /test/place {
>      if ($args = "id=2") {
>        return 301 https://new.example.com/test/place?$args;
>     }
> }

You might want to use $arg_id here (i.e., the $arg_<name> variable for
the <name> argument).  Otherwise, it won't work if any other arguments
are given.

> Or is there a way to do the following? That would be ideal.
>
> location = /test/place?id=2 {
>     return 301 https://new.example.com/test/place?id=2
> }

I don't think that's allowed.

> Unfortunately the above does not work. What is missing?

What doesn't work?

I would think your

> location = /test/place {

block would work, although not as shown, but I assume you just left
out the part that normally handles the request.  It would handle the
requests for id=1 and id=3 as before, and it's just the id=2 case that
gets redirected, right?

Lewis
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Jeff Dyke
I know this is not an answer to your question, but it begs another, mainly due to the if statement.  How many of these are you going to have?  https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/

You've likely considered this, but if not wanted to throw it out there.  Even if you are moving domains, could you create a separate route that you could key off rather than arg_id?

Random thoughts waiting for things to compile

On Thu, Oct 17, 2019 at 5:15 PM J. Lewis Muir <[hidden email]> wrote:
On 10/18, P.V.Anthony wrote:
> Currently have the following url,
>
> https://old.example.com/test/place?id=1
> https://old.example.com/test/place?id=2
> https://old.example.com/test/place?id=3
>
> Need to redirect only id=2 to another url.
>
> Did the following and it works for id=2. Need id=1 and id=3 to continue
> normally without change.
>
> location = /test/place {
>      if ($args = "id=2") {
>        return 301 https://new.example.com/test/place?$args;
>     }
> }

You might want to use $arg_id here (i.e., the $arg_<name> variable for
the <name> argument).  Otherwise, it won't work if any other arguments
are given.

> Or is there a way to do the following? That would be ideal.
>
> location = /test/place?id=2 {
>     return 301 https://new.example.com/test/place?id=2
> }

I don't think that's allowed.

> Unfortunately the above does not work. What is missing?

What doesn't work?

I would think your

> location = /test/place {

block would work, although not as shown, but I assume you just left
out the part that normally handles the request.  It would handle the
requests for id=1 and id=3 as before, and it's just the id=2 case that
gets redirected, right?

Lewis
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Patrick
In reply to this post by P.V.Anthony
On 2019-10-18 01:01, P.V.Anthony wrote:
> Currently have the following url,
>
> https://old.example.com/test/place?id=1
> https://old.example.com/test/place?id=2
> https://old.example.com/test/place?id=3
>
> Need to redirect only id=2 to another url.

This looks like a gradual migration of content to a new server. Try
using `rewrite' instead of `return'?


map "$uri?$args" $is_new_site {
    /test/place?id=2  1;
    default           0;
}

server {
        ...

    if ( $is_new_site ) {
        rewrite ^ http://new.example.com/${uri}?${args}? last;
    }

        ...

        # all the locations go here
}



Patrick
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
In reply to this post by J. Lewis Muir
On 18/10/19 5:15 am, J. Lewis Muir wrote:

> You might want to use $arg_id here (i.e., the $arg_<name> variable for
> the <name> argument).  Otherwise, it won't work if any other arguments
> are given.

Noted. I will change that.

>> Or is there a way to do the following? That would be ideal.
>>
>> location = /test/place?id=2 {
>>      return 301 https://new.example.com/test/place?id=2
>> }
>
> I don't think that's allowed.

Yah. Sad.

>> Unfortunately the above does not work. What is missing?
>
> What doesn't work?

I was hoping to get location = /test/place?id=2 { to work. Like you have
mentioned, it is not allowed.

> I would think your
>
>> location = /test/place {
>
> block would work, although not as shown, but I assume you just left
> out the part that normally handles the request.  It would handle the
> requests for id=1 and id=3 as before, and it's just the id=2 case that
> gets redirected, right?

That is where I need help with. I need help with requests for id=1 and
id=3. I need them to just pass through without any changes. I only need
id=2 to be redirected and id=2 redirection is working. I cannot figure
out how to pass through id=1 and id=3.

With the follow block id=1 and id=3 gives a 404 error.

location = /test/place {
      if ($args = "id=2") {
        return 301 https://new.example.com/test/place?$args;
     }
}

How to make id=1 and id=3 to work?

P.V.Anthony

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
In reply to this post by Jeff Dyke
On 18/10/19 5:26 am, Jeff Dyke wrote:
> I know this is not an answer to your question, but it begs another,
> mainly due to the if statement.  How many of these are you going to
> have? https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
>
> You've likely considered this, but if not wanted to throw it out there.  
> Even if you are moving domains, could you create a separate route that
> you could key off rather than arg_id?

Oh no. I was not aware of the "if" danger. Thank you for bringing that up.

I am not able to change the application. Is there another way without
using "if"?

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
In reply to this post by Patrick
On 18/10/19 9:03 am, Patrick wrote:

> This looks like a gradual migration of content to a new server. Try
> using `rewrite' instead of `return'?
>
>
> map "$uri?$args" $is_new_site {
>      /test/place?id=2  1;
>      default           0;
> }
>
> server {
> ...
>
>      if ( $is_new_site ) {
>          rewrite ^ http://new.example.com/${uri}?${args}? last;
>      }
>
> ...
>
> # all the locations go here
> }

This looks cool. Thank you for sharing this solution.

I am using ispconfig web control that only allows changes in the server
block.

I think map block is only allowed outside the server block. Is there
some way of setting a variable in the server block so that I can use the
config you have shared below?

if ( $is_new_site ) {
    rewrite ^ http://new.example.com/${uri}?${args}? last;
}

P.V.Anthony

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Patrick
On 2019-10-18 12:12, P.V.Anthony wrote:
> I am using ispconfig web control that only allows changes in the server
> block.

Without a map, try starting with:

if ( $uri?$args = /test/place?id=2 ) {
    rewrite ^ http://new.example.com/${uri}?${args}? last;
}

Then as the site migration continues turn that `if' test into a regexp
that will match the migrated components.


Patrick
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
On 18/10/19 12:20 pm, Patrick wrote:

> Without a map, try starting with:
>
> if ( $uri?$args = /test/place?id=2 ) {
>      rewrite ^ http://new.example.com/${uri}?${args}? last;
> }
>
> Then as the site migration continues turn that `if' test into a regexp
> that will match the migrated components.

I can get the following to work.

if ( $uri = /test/place ) {
       rewrite ^ http://new.example.com${uri}?${args}? last;
}

and this also works.

if ( $args = id=2 ) {
       rewrite ^ http://new.example.com${uri}?${args}? last;
}

Unfortunately I cannot get the suggested solution to work. Did I miss
some setting or quotes?

 > if ( $uri?$args = /test/place?id=2 ) {
 >      rewrite ^ http://new.example.com${uri}?${args}? last;
 > }


Tried the following and it works but is it safe?

if ( $request_uri = "/test/place?id=2" ) {
       rewrite ^ http://new.example.com${uri}?${args}? last;
}

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Patrick
On 2019-10-18 13:17, P.V.Anthony wrote:
> Tried the following and it works but is it safe?
>
> if ( $request_uri = "/test/place?id=2" ) {
>       rewrite ^ http://new.example.com${uri}?${args}? last;
> }

Awesome. By `safe' do you mean netsec, or memory-safe, or ?



Patrick
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
On 18/10/19 1:33 pm, Patrick wrote:

> Awesome. By `safe' do you mean netsec, or memory-safe, or ?

Like netsec and using "if" in the config.

I suppose for my case, I have to use "if".

Thank you very much for helping to solve this. I was cracking my head on
how to solve this. You really helped.

Thank you again.

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Patrick
On 2019-10-18 13:57, P.V.Anthony wrote:
> Like netsec and using "if" in the config.

The `if' part should be fine. The problem would be someone crafting a
URL that skips past the `=' check and yet is still parsed as `id=2' by
the underlying app.

Can the underlying old app also be changed to log an attack, and throw a
444 when it gets an `id' set to 2?



Patrick
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

J. Lewis Muir
In reply to this post by P.V.Anthony
On 10/18, P.V.Anthony wrote:

> On 18/10/19 5:26 am, Jeff Dyke wrote:
> > I know this is not an answer to your question, but it begs another,
> > mainly due to the if statement.  How many of these are you going to
> > have? https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
> >
> > You've likely considered this, but if not wanted to throw it out there.
> > Even if you are moving domains, could you create a separate route that
> > you could key off rather than arg_id?
>
> Oh no. I was not aware of the "if" danger. Thank you for bringing that up.
>
> I am not able to change the application. Is there another way without using
> "if"?

The "if" behavior is weird, so it's good to avoid it if you can, but
sometimes it really is the only way to do something.  And at the top of
that "If Is Evil" page it says:

  The only 100% safe things which may be done inside "if" in a location
  context are:

  * return ...;
  * rewrite ... last;

And in your example, you were doing a return inside an "if" which is
noted as being safe in a location context.

Lewis
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
In reply to this post by Patrick
On 18/10/19 2:59 pm, Patrick wrote:

> The `if' part should be fine. The problem would be someone crafting a
> URL that skips past the `=' check and yet is still parsed as `id=2' by
> the underlying app.
>
> Can the underlying old app also be changed to log an attack, and throw a
> 444 when it gets an `id' set to 2?

Will check it out. Thank you for the advice.

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
In reply to this post by J. Lewis Muir
On 18/10/19 9:47 pm, J. Lewis Muir wrote:

> And in your example, you were doing a return inside an "if" which is
> noted as being safe in a location context.

Phew! Thank you for the advice.

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

Aleksandar Lazic
In reply to this post by J. Lewis Muir
Hi P.V.Anthony.

Am 17.10.19 um 23:15 schrieb J. Lewis Muir:

> On 10/18, P.V.Anthony wrote:
>> Currently have the following url,
>>
>> https://old.example.com/test/place?id=1
>> https://old.example.com/test/place?id=2
>> https://old.example.com/test/place?id=3
>>
>> Need to redirect only id=2 to another url.
>>
>> Did the following and it works for id=2. Need id=1 and id=3 to continue
>> normally without change.
>>
>> location = /test/place {
>>      if ($args = "id=2") {
>>        return 301 https://new.example.com/test/place?$args;
>>     }
>> }
>
> You might want to use $arg_id here (i.e., the $arg_<name> variable for
> the <name> argument).  Otherwise, it won't work if any other arguments
> are given.

Have you tried Lewis suggestion with $arg_id, it looks exactly what you
searching for?

Untested:
location = /test/place {
      if ($arg_id = "2") {
        return 301 https://new.example.com/test/place?$args;
     }
}

The documentation for arg_ is here.
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_

>> Or is there a way to do the following? That would be ideal.
>>
>> location = /test/place?id=2 {
>>     return 301 https://new.example.com/test/place?id=2
>> }
>
> I don't think that's allowed.
>
>> Unfortunately the above does not work. What is missing?
>
> What doesn't work?
>
> I would think your
>
>> location = /test/place {
>
> block would work, although not as shown, but I assume you just left
> out the part that normally handles the request.  It would handle the
> requests for id=1 and id=3 as before, and it's just the id=2 case that
> gets redirected, right?
>
> Lewis
> _______________________________________________
> nginx mailing list
> [hidden email]
> http://mailman.nginx.org/mailman/listinfo/nginx
>

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: How to do location /test/place?id=2

P.V.Anthony
On 19/10/19 4:22 pm, Aleksandar Lazic wrote:

> Have you tried Lewis suggestion with $arg_id, it looks exactly what you
> searching for?
>
> Untested:
> location = /test/place {
>        if ($arg_id = "2") {
>          return 301 https://new.example.com/test/place?$args;
>       }
> }

I did try but it does not work when the uri has id=1 where id=1 should
remain and go to old.example.com.

The solution that works for me is as follows.

if ( $request_uri = "/test/place?id=2" ) {
       rewrite ^ http://new.example.com${uri}?${args}? last;
}

Works with "return" also.

P.V.Anthony
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx