2

I am trying to make a dynamic CORS proxy using Nginx, so I can use multiple API's from my front-end code without any CORS errors. My current way is using multiple location blocks, one for each domain, which works, but I would rather have a dynamic solution. My idea is to use x-proxy-target to specify the upstream hostname, and pass on the pathname. Nginx is running in Docker containers on Kubernetes, hence 10.245.0.10 being the resolver.

This works perfectly, and sends the CORS headers that are set at the bottom using add_header

location / {
      default_type application/json;
      if ($http_x_proxy_target = "") {
        return 400 '{"message": "No x-proxy-target header", "code": "PROXY_TARGET_NOT_SET"}';
      }

      resolver 10.245.0.10 [::1];
      set $cors '*';
      if ($http_origin != "") {
         set $cors $http_origin;
      }

      if ($request_method = "OPTIONS") {
        add_header Access-Control-Allow-Origin $cors always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
        add_header Access-Control-Allow-Headers * always;
        return 204;
      }

      proxy_hide_header Access-Control-Allow-Headers;
      proxy_hide_header Access-Control-Expose-Headers;
      proxy_hide_header Access-Control-Allow-Credentials;
      proxy_hide_header Access-Control-Allow-Origin;
      
      proxy_set_header x-proxy-target '';
      proxy_set_header User-Agent $http_user_agent;
      proxy_set_header Connection $http_connection;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Origin https://$http_x_proxy_target;
      proxy_set_header Host $http_x_proxy_target;
      proxy_set_header Referer https://$http_x_proxy_target/;

      proxy_pass https://google.com/;

      add_header Access-Control-Allow-Headers * always;
      add_header Access-Control-Expose-Headers * always;
      add_header Access-Control-Allow-Credentials true always;
      add_header Access-Control-Allow-Origin $cors always;
}

But when I change the proxy_pass to use the supplied upstream:

location / {
      default_type application/json;
      if ($http_x_proxy_target = "") {
        return 400 '{"message": "No x-proxy-target header", "code": "PROXY_TARGET_NOT_SET"}';
      }

      resolver 10.245.0.10 [::1];
      set $cors '*';
      if ($http_origin != "") {
         set $cors $http_origin;
      }

      if ($request_method = "OPTIONS") {
        add_header Access-Control-Allow-Origin $cors always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
        add_header Access-Control-Allow-Headers * always;
        return 204;
      }

      proxy_hide_header Access-Control-Allow-Headers;
      proxy_hide_header Access-Control-Expose-Headers;
      proxy_hide_header Access-Control-Allow-Credentials;
      proxy_hide_header Access-Control-Allow-Origin;
      
      proxy_set_header x-proxy-target '';
      proxy_set_header User-Agent $http_user_agent;
      proxy_set_header Connection $http_connection;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Origin https://$http_x_proxy_target;
      proxy_set_header Host $http_x_proxy_target;
      proxy_set_header Referer https://$http_x_proxy_target/;

      proxy_pass $scheme://$http_x_proxy_target$uri$is_args$args;

      add_header Access-Control-Allow-Headers * always;
      add_header Access-Control-Expose-Headers * always;
      add_header Access-Control-Allow-Credentials true always;
      add_header Access-Control-Allow-Origin $cors always;
}

I get the correct response using Postman, but the CORS headers are not set. I have tried moving the add_header lines to above the proxy_pass, to no avail. To me, this seems like a possible bug in Nginx, although I might just be making an obvious mistake. I can't find any mention of this problem anywhere, although it is a very specific usecase.

0 Answers0