-
Notifications
You must be signed in to change notification settings - Fork 799
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
start_http_server incapable to listen on IPv6 sockets #567
Comments
This code doesn't appear to be correct, a colon in a hostname does not mean that it is an IPv6 address. Nor do I think we should have hacks like this to workaround issues in libraries below us. As with the previous issue this appears to be a bug in cPython, and should be fixed there. |
DNS hostnames cannot contain the colon sign (
The only valid case where the address would contain colon is the IPv6 address, e.g. It would be great if you were proposing solutions to actual problems people see, such as the |
DNS is intended to 8-bit clean, technically any character (including null) can appear in a label. If we're passing a v6 address in to a function which doesn't mention only working on v4, then that's a bug in that function. The issue here appears to be that WSGIServer has broken v6 somehow. This repo has no v4 or v6 specific code, we're entirely relying on cPython to do the right thing. |
In theory, there is no difference between theory and practice. But, in practice, there is.
And the users of this repo are entirely relying on your code doing the right thing. Like binding to valid addresses. Which doesn't work now. Questions for you:
Thank you for answering these questions. |
Noone is forcing you to use it. In general start_http_server is meant to get you up and running quickly, in most serious applications I'd expect exposition to be via whatever existing http server the application uses.
I prefer to see problems fixed at their source, rather than workarounds layered throughout the stack. Is there a bug tracking this on the cPython side? |
|
That doesn't appear to be related to WSGI, are you sure that's the right issue? |
It is the correct issue. WSGI does the same thing as prometheus_client - blindly passes whatever it has down to So the link @zajdee provided is indeed the correct issue, unless you claim that fixing it at client_python is wrong but fixing it in wsgi is good, which would be weird. :) |
Well, I'm thinking about this all over and over again. In some operating systems and with a specific configuration, an IPv6 socket can listen for both IPv4 and IPv6 connections, IF the configuration allows so. The disadvantage is that the application sees that IPv4 connection as if it was initiated from the IPv6 address prefix An alternative to using just an IPv6 socket to handle both protocol connections is to use two sockets, based on current system's configuration, and multiplex connection processing. As for this specific problem, the workaround provided in my original post would help for the case where an IPv6 address would be provided (e.g. For hostnames resolving to address families of both protocols, the workaround wouldn't help at all. This is definitely something to be fixed in the code of TCPSocket, as both @brian-brazil: there is no light at the end of the tunnel to have this fixed in TCPSocket any time soon. Considering all of the above, including your statement that there is currently no IPv4/IPv6 specific code, would you be willing to make any change to the repo to at least enable listening on Thank you. |
I'm a bit confused then here. What exactly was fixed in cPython 3.8? |
|
Do you have a link to how they fixed it? I'd rather not reinvent the wheel. |
Well. Yes, I have a link, but you will probably not like the patch. (It has the same disadvantages as the workaround proposed in this bug report.) https://bugs.python.org/file39390/ipv6.patch |
As far as I see, we could also add an extra parameter to explicitely allow binding on IPv6. |
start_http_server is meant to be very very simple to get someone exposing metrics quickly, in principle it shouldn't even be allowing an address to be specified. If you've more complex needs, it's better to use your own http server rather than growing start_http_server into a does-everything solution. |
Hmm, that doesn't look like the patch that was used. This seems a bit messy on the Python end, so I'd like to get a better handle on how cPython intendeds to approach this. |
There seem to be two generations of the And yes, it's a bit messy. Dual-stack support is hard. |
I'm going to need to think a bit on this I think. May I ask why you want to listen only on v6 and not v4? |
Well, I'd prefer to listen on both protocols where applicable, e.g. when you specify a hostname which resolves to addresses of multiple protocols (e.g. If no bind address is specified, I prefer to listen on both protocols. This can be achieved two ways:
This seems way too low level for this library to me though and you're right this should all be handled elsewhere. If we at least enable listening on IPv6 |
Yeah, that's too low level for this library in general (before considering that start_http_server is meant to be simplistic) and it's also Linux specific. The challenge is that Python has changed things around with no explanation, and in contradiction of their discussions, so I don't have anything to really work from here. As this is the first time this has come up I'd suggest using a http server that does what you need and serving metrics from there, rather than trying to extend start_http_server. |
So it looks like there is still no solution to easily export some metrics using this client over IPv6 without relying on a separate http server ? |
For what it's worth, while some comments here say this should be fixed in python 3.8 I've tried 3.8 3.9 and 3.10(.0a5) to no avail (same address family not supported error), so this isn't quite over yet... EDIT: nevermind, it's the former implemetation that would have been fixed if it had been kept up to now, not wsgi's ; I read that too fast. Sorry for the noise. |
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567 Signed-off-by: Dominique Martinet <[email protected]>
So python fixed it in http.server only in the test/interactive function like this: def _get_best_family(*address):
infos = socket.getaddrinfo(
*address,
type=socket.SOCK_STREAM,
flags=socket.AI_PASSIVE,
)
family, type, proto, canonname, sockaddr = next(iter(infos))
return family, sockaddr
def test(HandlerClass=BaseHTTPRequestHandler,
ServerClass=ThreadingHTTPServer,
protocol="HTTP/1.0", port=8000, bind=None):
...
ServerClass.address_family, addr = _get_best_family(bind, port)
...
with ServerClass(addr, HandlerClass) as httpd: Instanciating a WSGIServer, HTTPServer or even TCPServer would not benefit from the fix so it's a misinterpretation to think that the original code using HTTPServer directly would have been fixed on newer versions - it's apparently up to applications to pick the address family and set it for their instance of the class (?!) The python issue tracking it https://bugs.python.org/issue24209 was apparently really just about python -m http.server and not about users of the library... I've opened PR #657 with a similar kludgy implementation; feel free to just close everything if you don't care /shrug |
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567 Signed-off-by: Dominique Martinet <[email protected]>
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567 Signed-off-by: Dominique Martinet <[email protected]>
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567 Signed-off-by: Dominique Martinet <[email protected]>
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes prometheus#567 Signed-off-by: Dominique Martinet <[email protected]>
Reproduce the fix in python3.8 http.server by doing a dns lookup and using the correct address family Fixes #567 Signed-off-by: Dominique Martinet <[email protected]>
This is a very similar issue to #132 and #69.
#69 was closed as a bug in cPython. That bug was resolved in cPython 3.8, however
client_python
has since migrated to WSGI.This is how it all behaves with the latest Python (3.8.5):
The issue lies with the
ThreadingWSGIServer
class, which defaults toAF_INET
address family.A workaround similar to bottlepy/bottle@af547f4 can be implemented in
exposition.py
:And voila, now it works as expected:
This is a non-invasive fix which doesn't break any existing code while at the same time provides those of us who wish our exporters listened on IPv6 sockets.
Is it possible to adjust
exposition.py
this way, please? Thank you.The text was updated successfully, but these errors were encountered: