skip to Main Content

My mirroring works just fine, and I am correctly getting the original request body in the mirror server.

However I need to access a response header called Location from the original upstream and forward it to my mirror. Typically the response header from upstream will be accessed using this variable: $upstream_http_<*header name*>, in my case $upstream_http_location.

However I want to access this in my mirror so I can forward the response header from my upstream to my mirror.

How do I do this? Here’s my current configuration, but it doesn’t work and I don’t see the header DAV-response in my mirror. Is there another way to access all $upstream_http headers in the mirror block?

I have the following request mirroring setup in nginx:

location /ops/opendata/DataAccessViewer/ {
  mirror /davmirror;
  proxy_pass  https://<upstream>/;
  proxy_redirect  https://<upstream>/ /; 
}

location /davmirror {
    internal;
    proxy_pass https://<mirror>;
    proxy_set_header DAV-Original-URI $request_uri;  # <<<<-- works!
    proxy_set_header DAV-tier internals; # <<<<-- works!
    proxy_set_header DAV-response $upstream_http_location; # <<<-- DOESNT WORK!
}

Update

Open to alternative solutions to achieve this using nginx. I am aware of other non-nginx workarounds and in-fact using those as fallbacks at the moment. Ideally we would want this to be nginx solution.

Update
This question seems to suggest that nginx is actually waiting on upstream response before resolving mirror?

Update

Verified that upstream does actually include a ‘Location’ Header:

enter image description here

Here’s all the headers I receive in the mirror. Note that DAV-response is missing

enter image description here

2

Answers


  1. if you’re having trouble accessing the Location header in the mirror block, it could be because the header isn’t included in the response from your upstream server,to check, you can use tools like curl or browser developer tools to look at the response headers, but if the Location header is there, then there might be an issue with how you’re setting up the mirror block.

    also, instead of using $upstream_http_, you can try using $sent_http_ which also has the response headers from the upstream server.

    something like this :

    location /ops/opendata/DataAccessViewer/ {
      mirror /davmirror;
      proxy_pass  https://<upstream>/;
      proxy_redirect  https://<upstream>/ /; 
    }
    
    location /davmirror {
        internal;
        proxy_pass https://<mirror>;
        proxy_set_header DAV-Original-URI $request_uri;
        proxy_set_header DAV-tier internals;
        proxy_set_header DAV-response $sent_http_location;
    }
    

    update
    So you can use the proxy_set_header directive with the $upstream_http_ variable like this :

    location /ops/opendata/DataAccessViewer/ {
      mirror /davmirror;
      proxy_pass  https://<upstream_server>/;
      proxy_redirect  https://<upstream_server>/ /; 
    }
    
    location /davmirror {
        internal;
        proxy_pass https://<upstream_server>/;
        proxy_set_header DAV-Original-URI $request_uri;
        proxy_set_header DAV-tier internals;
        proxy_pass_header Location;  #forwarding the Location header to the mirror server
    }
    

    or if still not working just try to use the proxy_pass_header directive along with the proxy_hide_header directive to achieve the desired result and please don’t forget to restart or reload your Nginx service !

    location /ops/opendata/DataAccessViewer/ {
      mirror /davmirror;
      proxy_pass  https://<upstream_server>/;
      proxy_redirect  https://<upstream_server>/ /; 
    }
    
    location /davmirror {
        internal;
        proxy_pass https://<upstream_server>/;
        proxy_set_header DAV-Original-URI $request_uri;
        proxy_set_header DAV-tier internals;
        proxy_hide_header Location;
        proxy_pass_header Location;
    }
    

    if still not working, you need to use the proxy_intercept_errors directive, because it tells Nginx to pass all error responses from the upstream server to the mirror server!

    location /ops/opendata/DataAccessViewer/ {
      mirror /davmirror;
      proxy_pass  https://<upstream>/;
      proxy_redirect  https://<upstream>/ /;
      proxy_intercept_errors on;
    }
    
    location /davmirror {
        internal;
        proxy_pass https://<mirror>;
        proxy_set_header DAV-Original-URI $request_uri;  # <<<<-- works!
        proxy_set_header DAV-tier internals; # <<<<-- works!
        proxy_set_header DAV-response $upstream_http_location; # <<<-- WORKS NOW!
    }
    
    Login or Signup to reply.
  2. Alright, so the issue here is a bit of head-scratcher. You see, Nginx’s mirror is a bit limited when it comes to waiting for original request to complete. This is probably why $upstream_http_location ain’t wokring in you’r mirror block.

    But hey, there’s a workaround you can try, though its not super clean. Have you heard of the post_action directive? It’s not well documented. But it letys you do stuff after your original proxy_pass is done and the response headers are revievd.

    Here’s how you could tweak your config:

    location /ops/opendata/DataAccessViewer/ {
      proxy_pass  https://<upstream>/;
      proxy_redirect  https://<upstream>/ /;
      post_action @davmirror;
    }
    
    location @davmirror {
      proxy_pass https://<mirror>;
      proxy_set_header DAV-Original-URI $request_uri;
      proxy_set_header DAV-tier internals;
      proxy_set_header DAV-response $upstream_http_location;
    }
    

    So, @davmirrorwill only kick in after the original proxy_pass gets its response. That way, $upstream_http_location should be populated and you can forward it to your mirror.

    Again, it’s not the most elegant solution. If you’re looking for something more robust, you might have to go for app-level logic or some custom module.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search