Repository: streamlit/streamlit

Issue:
default of browser.serverAddress is not actually "localhost"
### Checklist

- [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.
- [X] I added a very descriptive title to this issue.
- [X] I have provided sufficient information below to help reproduce this issue.

### Summary

https://docs.streamlit.io/develop/api-reference/configuration/config.toml#browser says the default of serverAddress  is "localhost". However, this can't be true, because if I `streamlit run` a file *without*
```
[browser]
serverAddress = "localhost"
```
in the config.toml

I get something like the following:

```
  You can now view your Streamlit app in your browser.

  Network URL: http://[some private IPv4 address]:8501
  External URL: http://[some public IPv4 address]:8501
```

And when I *add* the lines to the config.toml I get

```
  You can now view your Streamlit app in your browser.

  URL: http://localhost:8501
```

instead. (Which is the desired behavior in my case.)

localhost:8501 works to access the application either way.

This is either a documentation issue or a true bug.


Discussion:
**If this issue affects you, please react with a 👍 (thumbs up emoji) to the initial post.**

Your feedback helps us prioritize which bugs to investigate and address first.

![Visits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fstreamlit%2Fstreamlit%2Fissues%2F8629&title=visits&edge_flat=false)

Hey @wyattscarpenter, I have just tried to reproduce it on my M1 Mac, but there it behaves correctly and I correctly see 

```text
You can now view your Streamlit app in your browser.

Local URL: http://localhost:3000
Network URL: http://192.168.0.200:3000
```

The log lines seem to come from [this method](https://github.com/streamlit/streamlit/blob/1744c26477d9bf1f0a5dca3e7caca57f58cedaf2/lib/streamlit/web/bootstrap.py#L236-L269) where also the IP address is determined; when no respective config options are set, it seems to jump into [net_util.get_internal_ip()](https://github.com/streamlit/streamlit/blob/1744c26477d9bf1f0a5dca3e7caca57f58cedaf2/lib/streamlit/net_util.py#L66) which seems to determine the IP address via the `socket` package for the log. The bound address itself should depend on [tornado's listen method](https://www.tornadoweb.org/en/stable/tcpserver.html#tornado.tcpserver.TCPServer.listen) which we call [here](https://github.com/streamlit/streamlit/blob/develop/lib/streamlit/web/server/server.py#L196).

I don't have anything set in the `config.toml` file. Are you connected to a VPN or run the app in a virtual machine or container or so? And are you able to connect to the app via `localhost` despite the log showing a different address?
@raethlein interesting! I'm on Windows 10 (and the same thing happens in WSL on that machine). As far as I know I'm not in a VPN, VM, or container. I'm using streamlit 1.34.0 but it's been like this since I can remember. I can connect via localhost.

Looking at the method you cite, the cause is straightforward: I have server.headless set to true in the config as well. So the `elif config.get_option("server.headless")` triggers. Removing that makes my ouput
```
  Local URL: http://localhost:8501
  Network URL: http://10.150.8.250:8501
```
as well. 

Great!
Do you have a suggestion of how we could improve the docs to make this more clear or is it good as is then?
Going to transfer this issue into the docs repo so that it's in a more correct location

(Huh, looks like I can't for some reason 😕)
I'm not sure whether or not it's a docs issue. I don't know why the server.headless setting overrides the browser.serverAddress setting. Maybe it's a good reason, since the behavior seems intentional. I could imagine that for some reason a headless server might need to output the things it currently does. But maybe not.

Assuming the behavior is desirable: add note (in both places?) that server.headless overrides the browser.serverAddress setting.

If the behavior isn't desirable: make it not do that, I suppose.
good points, thanks 🙂 I guess the behavior is desirable since you can also connect via `localhost` and that the output prints are misleading. So looking [at the lines](https://github.com/streamlit/streamlit/blob/1744c26477d9bf1f0a5dca3e7caca57f58cedaf2/lib/streamlit/web/bootstrap.py#L253-L261) I guess that `localhost` should be printed out additionally when the mode is `headless`.
That seems like a pretty good solution to me.

Resolving patch:
diff --git a/lib/streamlit/web/bootstrap.py b/lib/streamlit/web/bootstrap.py
--- a/lib/streamlit/web/bootstrap.py
+++ b/lib/streamlit/web/bootstrap.py
@@ -250,15 +250,6 @@ def _print_url(is_running_hello: bool) -> None:
             ("Unix Socket", config.get_option("server.address")),
         ]
 
-    elif config.get_option("server.headless"):
-        internal_ip = net_util.get_internal_ip()
-        if internal_ip:
-            named_urls.append(("Network URL", server_util.get_url(internal_ip)))
-
-        external_ip = net_util.get_external_ip()
-        if external_ip:
-            named_urls.append(("External URL", server_util.get_url(external_ip)))
-
     else:
         named_urls = [
             ("Local URL", server_util.get_url("localhost")),
@@ -268,6 +259,11 @@ def _print_url(is_running_hello: bool) -> None:
         if internal_ip:
             named_urls.append(("Network URL", server_util.get_url(internal_ip)))
 
+        if config.get_option("server.headless"):
+            external_ip = net_util.get_external_ip()
+            if external_ip:
+                named_urls.append(("External URL", server_util.get_url(external_ip)))
+
     cli_util.print_to_cli("")
     cli_util.print_to_cli("  %s" % title_message, fg="blue", bold=True)
     cli_util.print_to_cli("")


Test patch:
diff --git a/lib/tests/streamlit/web/bootstrap_test.py b/lib/tests/streamlit/web/bootstrap_test.py
--- a/lib/tests/streamlit/web/bootstrap_test.py
+++ b/lib/tests/streamlit/web/bootstrap_test.py
@@ -151,6 +151,7 @@ def test_print_urls_remote(self, mock_get_internal_ip, mock_get_external_ip):
             bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
+        self.assertIn("Local URL: http://localhost", out)
         self.assertIn("Network URL: http://internal-ip", out)
         self.assertIn("External URL: http://external-ip", out)
 
@@ -175,6 +176,7 @@ def test_print_urls_remote_no_external(
             bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
+        self.assertIn("Local URL: http://localhost", out)
         self.assertIn("Network URL: http://internal-ip", out)
         self.assertNotIn("External URL: http://external-ip", out)
 
@@ -199,6 +201,7 @@ def test_print_urls_remote_no_internal(
             bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
+        self.assertIn("Local URL: http://localhost", out)
         self.assertNotIn("Network URL: http://internal-ip", out)
         self.assertIn("External URL: http://external-ip", out)