-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server only listens on IPv4 #61
Comments
Hi! I've received your issue and will provide a fix very soon. I'm sorry for the delay, was on holiday for a couple of days and didn't have time to work on this. |
No worries, we all have lives. I think a simple fix might be to just change the default host to |
I wanted to understand this issue so I looked at werkzeug's code. It has a naive algorithm to detect the address family: So if the host specified does not contain As you suggested there are two possible fixes:
But the real issue with changing the default hostname is the following: if someone uses TLS the certificate may contain the hostname and if it is specified as "localhost", it won't work with "127.0.0.1" as the certificate contains the hostname. If it was made properly and contains 127.0.0.1 and localhost it will work but if only "localhost" is there, it will fail... For example test_ssl.py fails in pytest-httpserver's test suite. Currently I have no good idea to fix this issue, as changing the default host may break TLS. I could release 2.0.0 but 1.0.0 has been released recently and releasing potentially breaking releases is not a good sign. I'm also thinking about writing a howto chapter about it or updating the documentation but that's also a half solution. Let me think on this for a while - or if you have ideas, please share it. Last but not least, I couldn't reproduce it in github actions, even if I added test test running on windows. For the record, I've just realized that this issue have been reported in PR #52 by @tenuki, but I wasn't able to understand it that time. |
Sounds like an upstream bug. Wekzeug should default to dual stack, not ipv4-only.
|
With a quick search I found this bug from 2015: pallets/werkzeug#33 I think werkzeug should require an IP address, and not a hostname for bind (if it makes decisions on the hostname string, then it is an issue) or call getaddrinfo() but that's a more complicated story. One idea which came up since my last comment is the following:
Alternatively, there would be just a check implemented in the |
I think I've found the solution 💡 In So, if
As the http client will also resolve the name with the same mechanism, it will use the same IP address the server bound so the connection will be successful. If there's no objection about it, I would proceed with this. |
Huh, that's actually a really smart and simple approach. I like it. |
There's one little issue with my "solution": Could you share a bit more information about the issue? What is the environment and which HTTP client are you using? Having a reproduction on my side would be very helpful. |
If you run this unit test with I'm using |
Thanks, I have a reproduction! Looking at it. |
Interestingly, only the second request made in line 69 (https://github.com/pimutils/vdirsyncer/blob/1a1f6f078882a8b7d1bd768a4a6544da8eec6cb1/tests/system/utils/test_main.py#L69 ) fails with the connection error, the first passes. In aiohttp's resolver, it resolves both addresses (ipv4 and ipv6) for localhost: But I'm still looking. |
I think I have a better understanding of this issue. In your test, you are testing with a bogus TLS setup. In the test a There's a retry logic in aiohttp which iterates on the resolved addresses (for localhost it contains 127.0.0.1 and ::1). If it cannot connect and catches I think that in the second request of your test case aiohttp fails with 127.0.0.1, it raises By fixing the address to 127.0.0.1 as you did, the list of IP addresses is only one so the I think that it is an edge case and it does not means that pytest-httpserver does not work on dual-stack systems. It means that if you want to test for a TLS error (or some other error which raises an exception derived from ServerConnectionError) that fails with a completely different error due to the re-trying implemented in aiohttp. What can be done in pytest-httpserver:
And probably more. I'll think about it. |
Ah, thanks for the research here, that was quite a tricky one. I think listening in dualstack is always a good choice if it doesn't introduce complexity or other issues. But it sounds like in my use case, it's best to specify |
There was a strange issue with dual-stack, so the documentation is updated. Fixes #61
Could you please look at the text I added to howto.rst? If there's some error or I missed something, I'm happy to fix it. |
I think that's clear enough. It's a very curious caveat though, and I think pretty much all systems nowadays are dualstack (even if they have public IPv6 connectivity). But given that I can't think of a way to completely get rid of it, that sounds good to me. |
Thanks! I want to note that pytest-httpserver does work on dual stack system (mine is dual stack, I presume that the github CI is also dual-stack), as long as the client implements retrying logic which falls back to 127.0.0.1 (requests does, aiohttp does). As discussed above, changing the default host to 127.0.0.1 is likely to cause errors in clients which use TLS connections whose certificate is issued for the "localhost" and does not issued for "127.0.0.1". |
There was a strange issue with dual-stack, so the documentation is updated. Fixes #61
It seems that the server only listens on IPv4, but
httpserver.host
returnslocalhost
.This will resolve to
::1
on a dual-stack system, so connecting to it will fail.httpserver.host
should either return an IPv4 address, or the server should listen on both.On most OSs, listening to just IPv6 implicitly listens on IPv4, so it might just be a matter of listening on the latter.
The text was updated successfully, but these errors were encountered: