I’ve used one of the many example on this site to run a React custom component which returns values back to the Streamlit app. This works fine if the values are generated in the React app itself. When I tried to retrieve the values from a remote API, I’m unable to resolve the value from the fetch call. I can see the value being returned by the API in the network inspector, but it’s not being bound to the variable I’m passing back to Streamlit. If I run the React app outside the Streamlit component host, it works fine. There’s probably a sandbox issue here, but I don’t see any meaningful error messages, or can I find guidance on how to achieve my goal. (I know I can make the API call that React is making directly from Streamlit, but that’d be working around the issue for my case).
Below is the React effect in my code (and there are more details in this post). The /api/ping end point is running on a different port and I use the React package.json proxy flag to forward the request:
Hey @asehmi, it sounds like your endpoint’s CORS response probably doesn’t handle the “null” origin. Currently, the Streamlit component iframe sandbox omits the “allow-same-origin” flag for security reasons, which means that the component is mounted in its iframe with a “null” origin. That is: your component’s origin is the string literal “null”. Some (many!) endpoints don’t handle this.
To fix it, you need to set an Access-Control-Allow-Origin: null header on your endpoint’s response. (Note that Access-Control-Allow-Origin: * will not work here - the “*” wildcard doesn’t handle the null origin.)
Here’s an example Flask app that demonstrates it:
import flask
app = flask.Flask(__name__)
@app.route("/api/ping")
def ping():
return "pong!"
@app.after_request
def after_request(response):
# If the request comes from a sandboxed iframe, the origin will be
# the string "null", which is not covered by the "*" wildcard.
# To handle this, we set "Access-Control-Allow-Origin: null".
response.headers.add(
"Access-Control-Allow-Origin",
"null" if flask.request.origin == "null" else "*")
response.headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization")
response.headers.add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS")
return response
(Oh, worth noting: we have some upcoming plans that should mitigate some of this pain. Because it’s a huge pain!)
Many thanks for your suggestions which unfortunately didn’t work for me. I have also tried serving the React component (hosted in Streamlit) and API requests (made by the React app) via a proxy. Technically Streamlit should only be aware of the proxy domain, on port 9009: (i) when it loads the React component, which is actually running on port 3001, and (ii) when the React component makes API calls, to a Flask server actually running on port 8888. The proxy has forwarding rules to serve both (i) and (ii) as if they were running on port 9009.
The proxy injects the following headers in all responses from API requests.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.