In reading the issue and examining the code the problem is that WSGIDav examines the requested scheme (http or https) vs the actual scheme. In otherwords, when you contact the server you use https://server.org. This request is SSL terminated by the NGINX reverse proxy which forwards the request as http://127.0.0.1:8080. The headers passed along all indicate a scheme of HTTPS, but the actual communication is on HTTP (non-SSL). The WSSGIDav code sees the incongruity and rejects the request with the 502 error.
This is correct behavior according to the standard. The issue is the code should be checking the X-Forwarded-Proto and then act accordingly, but currently does not. So adjusting the X-Forwarded-Proto will have no affect at the moment.
The only other options are to rewrite the headers so it looks like the original request was HTTP or to enable HTTPS on the WebDav backend - neither of which is trivial. Or you just do not use a reverse proxy.
As I have time I’ll research options and see if a solution presents itself.
Explanation:
The nginx map function operates by “mapping” a value to a variable based on a string (or other variable). In Nginx http headers are stored as variables with prefix $http_ and lowercase name of the header. Hence we are looking at the Destination header and storing a value based on what is there in $nossl_destination. The regex expression inside the map captures the “https:” part of the Destination header (we capture the : so we can evaluate for http as well as https). Everything after https is stored in an accessible variable called “$1” which we indicate as the value to be used for $nossl_destination by adding whitespace and stating it. We also have a value for straight http (based on configuration this may not be necessary but it is a good safety). Now in our location /seafdav we simply substitute a new Destination header with the “proxy_set_header Destination” and add http:$nossl_destination and everything should work.
There are various ways to write the regex and you can also use something akin to what @dani posted.
MOVE command is still failed ,after I add change the conf in nginx. Could you help me find the reason?
I am using seafdav in docker with my raspberry pi2.
seafdav.log shows that it is using http now:
Hi, for some unknown reason I couldn’t get the solutions posted by @eruditewriter and @dani to work at all (but huge thanks anyway for pointing in the right direction!).
After much trial and error I noticed that MOVE no longer fails when I completely strip scheme & hostname in the Destination header. More precisely:
I’m not sure if this is approach is technically correct / intended behaviour but at least it’s working for me. I’m also sure there’s an easier way to strip out the hostname than using the mapping above, but that’s for more seasoned nginx admins. (At the very least I’ll rename the nossl_destination variable to something more appropriate, e.g. plain_url or so.)
Any feedback is still appreciated of course.
The regexp I gave is not quite right, it also matches (sub)directories named seafdav. I’ve now settled for this:
# in the "location /seafdav" block:
set $destination $http_destination;
if ($destination ~* ^https?://[^/]+(/seafdav/.+)$) {
set $destination $1;
}
proxy_set_header Destination $destination;
I’d very much appreciate some official guidance in the manual. (That is, something more detailed than just a simple reference to the present thread…) I don’t think using TLS in the reverse proxy is only an edge case. It’s important enough to merit proper documentation.
@andi-blafasl This isn’t working for me. Is there anything else you did? I am using the exact same Apache Directive as you, just with my port changed (I am using a different WebDAV port).
I’m trying to implement the selected solution here in Nginx Proxy Manager gui. Can someone help?
I tried this but doesn’t seem to be correct:
Add a custom location of /seafdav, with the ip pointing to the address and port of the regular seafile server (or do you use the webdav port?).