posit-dev / py-shinylive

Python package for deploying Shinylive applications
https://shiny.posit.co/py/docs/shinylive.html
MIT License
42 stars 4 forks source link

Suggest --bind localhost for local preview #5

Closed dlukes closed 1 year ago

dlukes commented 1 year ago

Otherwise, the app just displays the following message:

Shinylive uses a Service Worker, which requires either a connection to localhost, or a connection via https.

wch commented 1 year ago

Can you explain exactly how to reproduce the problem, and how this change fixes it? It's not clear to me.

dlukes commented 1 year ago

Sure, happy to! (Sorry for being a bit terse in the OP, I was in a bit of a rush.)

Reproduction steps (I'm on macOS 13.0.1, using Firefox 107):

  1. Create an app with shiny create my-app.

  2. Export it with shinylive export my-app my-app/site.

  3. This shows the following suggestion:

    Run the following to serve the app:
    python3 -m http.server --directory my-app/site 8008
  4. Running the server as suggested logs the following message: Serving HTTP on :: port 8008 (http://[::]:8008/) ...

  5. Visiting http://[::]:8008 in the browser, I expect the app to start, but I get this message instead: Shinylive uses a Service Worker, which requires either a connection to localhost, or a connection via https.

:: is the IPv6 equivalent of 0.0.0.0, i.e. listen on all addresses on the local machine. But Shinylive seems to specifically require localhost (127.0.0.1 in IPv4, ::1 in IPv6) unless HTTPS is used. Setting up HTTPS just for testing is too much work, but restricting the server to listen on localhost only is just a --bind localhost away:

$ python3 -m http.server --directory my-app/site --bind localhost 8008
Serving HTTP on ::1 port 8008 (http://[::1]:8008/) ...

Visiting http://[::1]:8008/ in the browser then results in the app starting as expected.

So I figured that Shinylive should include --bind localhost in its suggestions on how to serve the exported website, to avoid this problem in the first place.

dlukes commented 1 year ago

Just adding that I see the same behavior on Fedora 37.

wch commented 1 year ago

OK, I understand now. It seems that the issue is that the message that is printed says that it's listening on ::, which is the IP6 equivalent to 0.0.0.0, and means it's listening on all interfaces:

$ python3 -m http.server --directory site 8008
Serving HTTP on :: port 8008 (http://[::]:8008/) ...

But if you visit http://[::]:8008/ or http://0.0.0.0:8008/, neither of those is a localhost address, and so the browser's security sandbox won't allow running the service worker.

Because the server is listening on all interfaces, it is possible to visit localhost addresses like http://[::1]:8008/, http://127.0.0.1:8008/, or http://localhost:8008/, and the app will run just fine.

That said, I think you're right that it makes sense to add --bind localhost, because users might copy and paste the http://[::]:8008/ address printed by http.server, and because there's no reason to listen to other interfaces, since these apps won't run if visited from an external interface.

dlukes commented 1 year ago

Yes, you are exactly right: it's not about the current tip being technically wrong, it's about making http.server show a more helpful hint. Sorry for the confusion!