1

My nginx server is currently setup to serve all requests via uwsgi_pass:

location / {
  uwsgi_pass unix:///tmp/uwsgi-zerocater.sock;
  include uwsgi_params;
  uwsgi_read_timeout 7200;
  client_max_body_size 20M;
}

In my application code, I've set a cookie called new_fe whose value is either "True" or "False".

When the value is "True", I want to instead proxy_pass to another external server, but only for specific routes. Something like the following pseudo code:

location ~ "^/my/complicated/regex$" {
  if ($cookie_new_fe = "True") {
    # pass the request to my other server
    # at something like http://other.server.com
  } else {
    # do the usual uwsgi stuff
  }
}

How can I do this? I'm still a bit new to nginx, so please pardon the question if it's something simple I'm missing.

2
  • You can probably do this with some sort of map (because you can do just about anything with maps in nginx), but seriously, just put your new codebase on a separate vhost.
    – womble
    Oct 14, 2015 at 5:27
  • @womble I'm after a temporary solution: I'm in the process of carving a monolithic app into smaller, stand-alone apps. Problem is that nginx & uwsgi exist on one EC2 instance, but the external host is on Heroku. Until I can transition the code wholesale, I need to be able to get by with tom foolery like this and not (seriously) break the existing app. Do you have an example of how to do this with maps?
    – neezer
    Oct 14, 2015 at 6:13

2 Answers 2

0

As a temporary solution this should work:

location ~ "^/my/complicated/regex$" {
  if ($cookie_new_fe = "True") {
    error_page 418 = @proxy;
    return 418;
  }

  # do the usual uwsgi stuff
}

location @proxy {
    # do proxy stuff
}
5
  • Haha! 418 I'M A TEAPOT status... might use this solution just for that. ;)
    – neezer
    Oct 14, 2015 at 6:58
  • Also, would I need to duplicate the innards of location / inside location ~ "^/my/complicated/regex$" with this solution?
    – neezer
    Oct 14, 2015 at 7:01
  • Yes. You have to copy all uwsgi stuff
    – Alexey Ten
    Oct 14, 2015 at 7:14
  • @alexy-ten Tangential to this question: is there anyway to match multiple routes with the same logic? Just looking for a way to avoid the massive amount of copy/pasting this will entail...
    – neezer
    Oct 14, 2015 at 14:59
  • Use includes.
    – Alexey Ten
    Oct 14, 2015 at 14:59
0

I looked into maps a bit more and came up with this solution, which seems to work (uses both @womble's and @alexey-ten's suggestions):

map $cookie_new_fe $serve_request_from {
  default @uwsgi;
  "True" @proxy;
}

server {

  # ...

  # BEGIN Routes to switch based on value of $cookie_new_fe
  location ~ "^/my/complicated/regex$" {
    error_page 418 = $serve_request_from;
    return 418;
  }
  # END

  location / {
    error_page 418 = @uwsgi;
    return 418;
  }

  location @uwsgi {
    uwsgi_pass unix:///tmp/uwsgi-origserver.sock;
    include uwsgi_params;
    uwsgi_read_timeout 7200;
    client_max_body_size 20M;
  }

  location @proxy {
    proxy_pass https://other.server.com;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

This way I have minimal duplication across the many routes that I'll need to add here in the interim, until this migration is complete.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .