mdBook
mdBook copied to clipboard
Listen on 127.0.0.1
mdbook listen on localhost and [::1] by default but why not listen on 127.1 (127.0.0.1) too so 127.1:3000 and 127.0.0.1:3000 works in the browser?
Could you explain why this is preferable?
It is very surprising to me that when I tried browsing 127.1:3000 and it didn't work, it should be least surprising if it works for localhost it should work for 127.0.0.1, I don't understand why do we only want localhost.
So instead of confusing others if they really started the server and double check that and figure it out that it only works for localhost but not 127.0.0.1, we should have this.
Well as you probably know, on dual-stack machines localhost should resolve to both 127.0.0.1 and ::1 - it's just that the mdBook code only binds to whatever the OS returns as the highest preference.
e.g. on modern Linux, if IPv4 and IPv6 are both enabled, then glibc favours IPv6 by default (but you can make the it prefer IPv4 instead by setting precedence ::ffff:0:0/96 100 in /etc/gai.conf, and if you do that then mdBook will indeed bind to current code bind to 127.0.0.1 instead of ::1).
If you wanted to ensure that you bind to both (in a future-proof way so that it would also run on IPv6-only machines - although I realise that these are currently rare), then you could perhaps try to match both IPv4 and IPv6 sockets to the requested hostname, and if both succeed, then start to listen on both addresses (an example of listening on multiple sockets with warp is included at https://stackoverflow.com/questions/61423911 ).
Whether that would be considered sufficiently important an enhancement to merge, I don't know unfortunately.
Some observations:
- The code allows you to explicitly bind to an IP address already if you want to do that using e.g.
-n 127.0.0.1. - mdBook already prints out the URL like this
Serving on: http://localhost:3000(warp also printslistening on http://[::1]:3000at couple of lines later - assuming IPv6 has been prioritised) - and navigating to either URL will work regardless of whether the IPv4 or IPv6localhosthas been bound to. - OS mechanisms (see above) also exist if you want to prefer IPv4 over IPv6.
That having been said, you found this behaviour surprising (and sufficiently annoying to create a PR), so others may too. In summary "dunno", but hopefully some of the above is useful! :-)
The code allows you to explicitly bind to an IP address already if you want to do that using e.g. -n 127.0.0.1.
A user shouldn't need to do that by default for serve.
mdBook already prints out the URL like this Serving on: http://localhost:3000 (warp also prints listening on http://[::1]:3000 at couple of lines later - assuming IPv6 has been prioritised) - and navigating to either URL will work regardless of whether the IPv4 or IPv6 localhost has been bound to.
I did saw that but I navigated to http://127.1:3000 which does not work, I always thought if it works on localhost it works on 127.0.0.1 since that always works for me.
Well as you probably know, on dual-stack machines localhost should resolve to both 127.0.0.1 and ::1 - it's just that the mdBook code only binds to whatever the OS returns as the highest preference.
A dual-stack machine? I use linux but using 127.0.0.1 does not work for me, only localhost works without this patch.
Yup, annoying enough that I directly create a PR for this (I also patched it for my local one). If I find any alternatives I wouldn't have send a PR but so for among all other applications I have used, this is the first time I encounter this surprising behavior.
This sounds like what's been happening to me on a macOS 12.4 machine which has both IPv4 and IPv6 connectivity.
If I just use mdbook serve --open, mdbook resolves localhost to ::1 and binds to that IPv6 address, but the browser (Brave) seems to prefer IPv4 and resolves localhost to 127.0.0.1.
$ mdbook serve --open
2022-05-31 00:22:09 [INFO] (mdbook::book): Book building has started
2022-05-31 00:22:09 [INFO] (mdbook::book): Running the html backend
2022-05-31 00:22:09 [INFO] (mdbook::cmd::serve): Serving on: http://localhost:3000
2022-05-31 00:22:09 [INFO] (mdbook): Opening web browser
2022-05-31 00:22:09 [INFO] (warp::server): Server::run; addr=[::1]:3000
2022-05-31 00:22:09 [INFO] (warp::server): listening on http://[::1]:3000
2022-05-31 00:22:09 [INFO] (mdbook::cmd::watch): Listening for changes...
I ended up working around it by including --hostname 127.0.0.1 on the command line (which is not a big deal, it's in a Makefile and I'm actually typing make serve either way).
Suggestions:
- If "localhost" resolves to both protocols, bind to both protocols. (I know it's "non-trivial but not too difficult" in C, I would imagine it's the same in Rust.)
- If listening on both protocols is overly difficult, maybe add
-4and-6options (mutually exclusive) which tellmdbook servewhich protocol to bind to in cases where the hostname resolves to addresses in both families. - Whatever the "listening on" value in the log says (i.e.
http://[::1]:3000in the example above), send that string to the browser, rather thanhttp://localhost:3000.
i meet this problem too on windows 10, i disabled ipv6, and visit 127.0.0.1 or 192.168.50.xxx not working , only localhost worked well, i use 0.4.21. i set -n 0.0.0.0 , worked well