Localhost refused to connect
After setting the port to a specific integer and making sure the port was open on my router the would be terminal window shows a broken page icon that says Localhost refused to connect.
I'm having the same issue. Are you using it within a docker container?
You can modify the source code simply running ttyd server. it will work or you dont need use this library if you're running ttyd server as a process on linux server you can directly render the iframe on the streamlit.
directly render without this module:- (you must run ttyd server)
ttyd_url = "http://localhost:7681" # Replace with the actual URL of your TTYD page
iframe_html = f''
st.write(iframe_html, unsafe_allow_html=True)
another method to call the ttyd iframe without this module:- (you must run ttyd server) import streamlit as st iframe_url = "http://localhost:7681" st.components.v1.iframe(iframe_url, width=800, height=400)
Using this library update the source code in actual python site-packages where your source code is installed.
ttydproc = subprocess.Popen( # f"ttyd {flags} {cmd}", f"ttyd bash", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, )
This project doesn't properly bundle the ttyd executable it depends on, so the calls to ttyd don't work. It only works if you git clone this project as if you were the developer and execute from that exact folder.
Also, it's really bad form to distribute executables without clear provenance in Python package. The proper way to set this up would have to have GitHub Actions script that compiles https://github.com/tsl0922/ttyd from source and injects into the generated Python wheel on a per platform basis.
Happy new year and thanks @jbarlow83 for the feedback.
Although at this point I am not integrating ttyd building from source but I have added a way to provide your own ttyd binary path to the terminal function.
Also the package is now relatively better designed for distribution using flit
Thanks again.
Thanks for the quick feedback.
Regarding the use of Docker, typically Docker containers acquire a private IP address that is distinct from the host computer (unless port mapping is setup). Also, the iframe asks the user's browser to open an additional port, so to direct the browser to the correct location, it needs to do something like this:
def get_host_url_with_port(port: int) -> str:
"""Get the host URL."""
host_url = st.context.headers["host"]
try:
host, _streamlit_port = host_url.split(":", maxsplit=1)
except ValueError:
host = host_url
return f"//{host}:{port}" # Use the same protocol
That checks the browser's headers to see what
Then when it's time to show the iframe, use:
iframe(src=get_host_url_with_port(port))
There might be cases where st.context.headers["host"] isn't accurate enough but this should be a good start.
I think it is simpler to let users explicitly set the parameters when there is non-transparency in network between host and container. How about modifying port parameter to ttyd_port and adding an iframe_port argument which will equal ttyd_port if iframe_port not explicitly provided?
This will be a breaking change but should be ok.
The issue isn't the port, it's the server. Setting Docker aside for the moment, if you run streamlit anywhere other than localhost, streamlit-ttyd won't work, because it always tries to use an iframe on localhost.
I have added your fix but not tested. Could you please help test the code on your end?