reflex-dev / reflex

πŸ•ΈοΈ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
17.95k stars 993 forks source link

Websocket Error when local hosting in GitHub Codespaces #2823

Open Sprocketer opened 3 months ago

Sprocketer commented 3 months ago

When attempting to access a locally hosted website in GitHub Codespaces with port forward, the following error pops up: Cannot connect to server: websocket error. Check if server is reachable at wss://curly-guide-94xqrvv6pgw3pxww-8000.app.github.dev/_event

To reproduce it, just run reflex init reflex run in a GitHub codespace

then go to the forwarded port image

Absolutely no clue why this happens so far

Sprocketer commented 3 months ago

Extra info: when pinging the forwarded port 8000 (for the backend) at 127.0.0.1:8000/ping, you do get the response pong back

Sprocketer commented 3 months ago

@Lendemor @masenf @ElijahAhianyo Sorry for the tag but you're the top contributors to the repo and I think this is quite crucial to fix before 1.0 as GitHub Codespaces is a widely used tool for development and therefore it's crucial for developers to be able to develop using it - it's probably a relatively simple fix as well.

masenf commented 3 months ago

Maybe a documentation issue... if the port 8000 is not "public", then you have to access it via HTTP to allow github to authenticate you, then you can connect the websocket.

For example, I open the port 8000 and get {"detail": "Not found"}: https://ubiquitous-train-v64gj575pvcp4pg-8000.app.github.dev/

Then when I open the port 3000 at https://ubiquitous-train-v64gj575pvcp4pg-3000.app.github.dev it actually connects and the app is fully functional.

I wonder if there is a way to automate this, or at the very least print a message when starting reflex in a codespace, suggesting to access the port 8000 tunnel first.

Sprocketer commented 3 months ago

I'm gonna take a look at this - gimme a bit

Sprocketer commented 3 months ago

@masenf What I found is that I just had to set the port 8000 to public (in port forwarding), and then it works - I don't even have to access it. Weirdly it has to be HTTP, can't be HTTPS either.

The bigger issue that I see here is that Reflex doesn't automatically port forward 3000 and 8000 - when you do follow the localhost:3000 link with ctrl+click, VSCode does then set up port forwarding (even though Reflex should do it when you run the app at all) - but the even bigger issue is that you have to manually set up the port forwarding for the backend port (8000) and switch it to public - both of these port forwardings should be automated.

Sprocketer commented 2 months ago

@masenf done further testing - it's definitely the fact that you have to manually set the port forwarding for the backend port (8000 by default) to public - there should be some way to detect if code is running in codespaces and then automatically set this up - I'm not well-versed in this so hopefully your team can add this to a to-do of some sort 🀞.

masenf commented 2 months ago

Our devcontainer json already forwards ports 3000 and 8000 by default, but we cannot make them public because the workspace is not trusted (https://github.com/microsoft/vscode-remote-release/issues/6363).

It might be possible to have reflex pass the GITHUB_TOKEN in the request if we know we're running from a codespace; we already have some conditional logic in the framework to handle that, but this would have to be plumbed fairly deep.

masenf commented 2 months ago

@Sprocketer so i had an idea and put up a draft PR: https://github.com/reflex-dev/reflex/pull/3044

Essentially, if the app is running in a codespace, reflex will add a link from the connection banner to a new endpoint on the backend. If you click this link and are logged into github, it will automatically authenticate your session. After closing the tab, the app will start to work. This seems like the simplest approach (try it in a codespace πŸ˜‰).

Let me know if you have any other ideas for a way to do it with even less friction.

Sprocketer commented 2 months ago

@masenf looks cool! How do I build/use this from the files in the draft pr - never done that before

masenf commented 2 months ago

You just go to the PR, click the Code button, then Codespaces tab, then create a codespace from the PR. It takes a while to boot up, let it run the setup script, then when you poetry run reflex ... you will use the version from the PR. Makes testing PRs simple when away from your normal dev environment.

I also attached a video so you can see the flow (some stuff sped up/cut out for brevity)

https://github.com/reflex-dev/reflex/assets/1524005/4b1bd4ce-0f0a-4f73-abf2-e3e42a526c18

Sprocketer commented 2 months ago

@masenf Super, thanks for that πŸŽ‰ - Just an idea: maybe Reflex somehow automates a request to the authentication URL, or redirects to it and then back to the original site automatically? (both options streamline developer experience)

I haven't worked with GitHub APIs or (such) tooling before so I'm not sure how viable either option is

masenf commented 2 months ago

yeah, that's probably do-able. i wonder if it would would get blocked by a popup blocker. i'll try out some different ideas to reduce the friction.

Sprocketer commented 2 months ago

Sounds good - popup blockers can always be disabled for certain conditions so I wouldn't make that the top critera for which implementation to choose - whichever you think works best though

masenf commented 2 months ago

So i tried to open the page with window.open or by creating a link with target=_blank and clicking it: both of these are blocked by popup blocker.

Then I tried loading the backend in an iframe, but this doesn't authenticate the session for the outer page.

Then I tried creating a link and clicking it without the target and that works, but then i can't easily get back to the app πŸ˜”

masenf commented 2 months ago

thanks for the feedback, i seem to have a "no touch" mechanism for handling this now. will require some clean up and testing, not sure when it can actually merge

Sprocketer commented 2 months ago

thanks for the feedback, i seem to have a "no touch" mechanism for handling this now. will require some clean up and testing, not sure when it can actually merge

Nice! I'll look forward to checking it out - I'll be notified when you update the draft PR