25

I'd like to add a parameter in the URL in a proxy pass. For example, I want to add an apiKey : &apiKey=tiger
http://mywebsite.com/oneapi?field=22 ---> https://api.somewhere.com/?field=22&apiKey=tiger Do you know a solution ?

Thank's a lot, Gilles.

server {
      listen   80;
      server_name  mywebsite.com;
      location /oneapi{
      proxy_pass         https://api.somewhere.com/;
      }
    }

5 Answers5

33
location = /oneapi {
  set $args $args&apiKey=tiger;
  proxy_pass https://api.somewhere.com;
}
Jack
  • 1,892
  • 1
  • 19
  • 23
  • 9
    If $args is empty you set $args to ?&apiKey=tiger. It's not right. – Jack May 15 '13 at 18:35
  • In facts, I validated too fast your answer and the edited solution worked. In the question $args isn't empty => ?field=22&apiKey=tiger –  May 19 '13 at 22:20
  • 3
    This does not appear to work when using a `location /somepath` block (no equals sign). I had to use `rewrite ^(.*)$ $1?$args&myParam=value break;` instead at the same spot. – nerdherd Oct 08 '14 at 21:27
  • great solution, but see my solution if you want it to work when $args is empty – warch Apr 25 '18 at 09:15
  • This is not cleanest way. Please take a look mine. – RammusXu Mar 19 '21 at 06:50
16

The other answers do not work if $args is empty.

This also works if $args is empty.

location /oneapi {
  set $delimeter "";

  if ($is_args) {
    set $delimeter "&";
  }

  set $args "$args${delimeter}apiKey=tiger";

  proxy_pass https://api.somewhere.com/;
}
warch
  • 2,387
  • 2
  • 26
  • 43
4

github gist https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7

    #set $token "?"; # deprecated

    set $token ""; # declar token is ""(empty str) for original request without args,because $is_args concat any var will be `?`

    if ($is_args) { # if the request has args update token to "&"
        set $token "&";
    }

    location /test {
        set $args "${args}${token}k1=v1&k2=v2"; # update original append custom params with $token
        # if no args $is_args is empty str,else it's "?"
        # http is scheme
        # service is upstream server
        #proxy_pass http://service/$uri$is_args$args; # deprecated remove `/`
        proxy_pass http://service$uri$is_args$args; # proxy pass
    }

    #http://localhost/test?foo=bar ==> http://service/test?foo=bar&k1=v1&k2=v2

    #http://localhost/test/ ==> http://service/test?k1=v1&k2=v2
Ahmad
  • 69,608
  • 17
  • 111
  • 137
AnJia
  • 129
  • 7
  • 1
    the answer would be better if you explained the code and the reason for it. – ADyson Oct 16 '17 at 09:18
  • @ADyson sorry, my english is not very good , but i am working on it. I will improve my answer. – AnJia Oct 17 '17 at 04:07
  • Close, but here when `$args` is empty, `http://localhost/test/` will actually redirect to `http://service/test??k1=v1&k2=v2` (two integorrations signs), which seems to be caused by nginx turning `$is_args` to `?` when concatenating to another string, even if empty. Removing `$is_args` from the final statement in turn will cause `$args` to lack the preceding token when not empty. – Mahn Dec 12 '17 at 17:45
  • if `$args` is empty,the `$token` is `?` ,so ` set $args "${args}${token}k1=v1&k2=v2"` you'll get empty str+`?`+custom params. if `$args` is not empty ,the `$token` is `&`, the `L8` code is `?old args`+`&`+custom params. – AnJia Dec 13 '17 at 07:59
  • @Mahn the nginx's doc http://nginx.org/en/docs/http/ngx_http_core_module.html#var_is_args `?” if a request line has arguments, or an empty string otherwise` – AnJia Dec 13 '17 at 08:07
  • if `$args` is empty,the `$is_args` is `empty string`,so `$token` is `?`, so `http://service/$uri$is_args$args` eq `http://service/$uri$tokenk1=v1&k2=v2` eq `http://service/$uri?k1=v1&k2=v2`. if `$args` is not empty,the `$is_args` is `?`,so `$token` is `&`, so `http://service/$uri$is_args$args` eq `http://service/$uri?$args$tokenk1=v1&k2=v2` eq `http://service/$uri?$args&k1=v1&k2=v2`. – AnJia Dec 13 '17 at 08:10
  • @AnJia I understand what you were trying to do, but in my real life tests the nginx documentation appears to be wrong, `$is_args` is never empty when concatenated to another string. Test it yourself if you'd like. – Mahn Dec 13 '17 at 15:45
  • @Mahn yeah, u r right, i'll modify my anwser. i create a github gist https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7 – AnJia Dec 14 '17 at 04:14
3

Here's a way to add a paramater in nginx when it's unknown whether the original URL had arguments or not (i.e. when you have to account for both ? and &):

location /oneapi {
    set $pretoken "";
    set $posttoken "?";

    if ($is_args) {
        set $pretoken "?";
        set $posttoken "&";
    }

    # Replace apiKey=tiger with your variable here
    set $args "${pretoken}${args}${posttoken}apiKey=tiger"; 

    # Optional: replace proxy_pass with return 302 for redirects
    proxy_pass https://api.somewhere.com$uri$args; 
}
Mahn
  • 16,261
  • 16
  • 62
  • 78
1

For someone get here. Thanks for https://serverfault.com/questions/912090/how-to-add-parameter-to-nginx-query-string-during-redirect

The cleanest way on 2021 is:

rewrite ^ https://api.somewhere.com$uri?apiKey=tiger permanent;

If a replacement string includes the new request arguments, the previous request arguments are appended after them

proxy_pass way


upstream api {
    server api.somewhere.com;
}

location /oneapi {
    rewrite ^/oneapi/?(.*) /$1?apiKey=tiger break;
    proxy_pass https://api$uri$is_args$args;
}
RammusXu
  • 1,180
  • 1
  • 7
  • 21