tobychui / zoraxy

A general purpose HTTP reverse proxy and forwarding tool. Now written in Go!
https://zoraxy.aroz.org
GNU Affero General Public License v3.0
3.09k stars 188 forks source link

[BUG] Cannot handle HTTP 301 response correctly #71

Closed wcp1231 closed 1 year ago

wcp1231 commented 1 year ago

Describe the bug Let's say I have a domain example.com and want to proxy http://example.com/linkding to selfhost linkding.

In order to handle linkding/* and linkding/static/* correctly, I set the linkding base path to linkding/.

I add virtual directory config, /linkding/ to 192.168.1.x:9090/linkding/.

When I request http://example.com/linkding it redirects to http://example.com/linkding/linkding/login

I found that when I request 192.168.1.x:9090/linkding/ directly it would respond:

< HTTP/1.1 302 found
< Location: /linkding/login
< ...

And zoraxy will overwrite the Location header, set it to /linkding + /linkding/login.

https://github.com/tobychui/zoraxy/blob/50f222cced924f8f049c6a2d2652cb67146dc10c/src/mod/dynamicproxy/dpcore/dpcore.go#L368-L371

To Reproduce See above

Expected behavior When overriding Location, consider cases where the Location header already contains PathPrefix.

tobychui commented 1 year ago

Thanks for the bug report.

To be honest I have been figuring out a solution for this for a long time, like the one reported in #39, there are always weird exceptions regarding the Location header handling. But I am not sure how to design a logic to handle the detection and location trimming automatically.

There are many systems out there that returns tons of weird things as Location header, I have seen a few like (assuming its base target is localhost:8080)

I have completely no idea how do you suppose to distinguish between the last two. Currently I am using the prefix trim method so that some projects like wordpress can be redirected correctly when it is proxied with subpath in the target (e.g. locahost:8080/wordpress). It would be nice if you could propose an auto detection logic / algorithm and we can discuss this further on how to fix this.

wcp1231 commented 1 year ago

I'm not very familiar with these systems and situations, so I can't give a solution that will work for these situations right now.

But I think you can construct some test cases based on these scenarios and then we can find a suitable solution based on these test cases.

tobychui commented 1 year ago

Ok, I will see if I can reproduce the same issue and try to figure out how to fix this 🤔

tobychui commented 1 year ago

Hi @wcp1231

I am able to reproduce your issue, but I notice this is an expected behavior of virtual directory reverse proxy. Let say you setup your vdir as /myservice, when the proxied service requires a Location header for /admin/login, the reverse proxy is suppose to redirect to /myservice/admin/login instead of /admin/login.

I have look at the README from linkding and found they didn't support virtual directory type of proxying as shown in the Apache config (notice the / after ProxyPass)

<VirtualHost *:9100>
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass / http://linkding:9090/
    ProxyPassReverse / http://linkding:9090/
</VirtualHost>

To make your setup works, please use subdomain proxy instead of virtual directory and create a rule like linkding.example.com. If you have no further questions, please close this issue. Thank you for using Zoraxy!

wcp1231 commented 1 year ago

Yes... The behaviour of the virtual directory look correct.

It seems that I was looking for reverse proxy function similarity to nginx, which proxy example.com/linkding to 192.168.1.x:9090/likding, so I feel strange for behaviour of vdr before.

thx.