Allow backend URLs to be configurable via window variables#11378
Allow backend URLs to be configurable via window variables#11378
Conversation
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) ✅ license/snyk check is complete. No issues have been found. (View Details) |
✅ PR preview is ready!
|
24d1431 to
8cc01b7
Compare
92dddcb to
0b1ee90
Compare
| // weird-looking triple `replace()`. | ||
| return decodeURIComponent( | ||
| document.location.pathname | ||
| pathname |
There was a problem hiding this comment.
Using document.location.pathname here seems to have been an accident as we pass document.location.pathname to this helper function where it's used as the pathname variable but then proceed to never use the variable.
There was a problem hiding this comment.
oh :( I think we might want to add a linting rule to catch unused parameters. I added it as tech debt here (cc @sfc-gh-bnisco)
| // rerun the current page. | ||
| pageScriptHash = currentPageScriptHash | ||
| } else if (window.__STREAMLIT_BACKEND_URL) { | ||
| // We currently don't support navigating directly to a subpage of a |
There was a problem hiding this comment.
Is it unreasonable to leave the subpage still tied to the index.html and the backend url does not change based on the page being viewed? Or does that break down in some way?
There was a problem hiding this comment.
@kmcgrady is OOO. I think this should work fine, but not 100% sure. Might need some manual validation.
There was a problem hiding this comment.
I think there's some trickiness here so would prefer to just leave this behavior explicitly unsupported for now. I think we'll need to do some work on both the OSS and SiS vNext ends to fully support this behavior, and until then this behavior not working probably won't be a big deal.
The main issue is that I think that the document.location here will effectively be hidden from the user since they generally won't see the URL of the Streamlit app embedded in an iframe without doing something like poking around in developer tools. If we want to support being able to navigate directly to a subpage of a multipage app in the vNext world, then we'd need some way of getting the path of the page that we're navigating to from the Snowsight URL (which is assuming where this info would live) into the path used in the iframe.
At this point, things start to break down because the way that we currently know which parts of the URL are part of the base path and which part is the page name is based on what piece of document.location.href we've determined to be the base path, and setting a different base path messes with this.
There was a problem hiding this comment.
This is supported today - Snowsight supports deep linking into a sub-page directly and we should continue to do so for vNext. You're right though, this wouldn't work OOTB given how we iteratively guess the base URL by guessing host-config. I don't have something clever to suggest as a workaround other than being able to define a static base path which is not a great option. We can leave undefined for now but would like to fast follow.
There was a problem hiding this comment.
Pull Request Overview
This PR enables configurable backend URLs by reading new window variables and refactors URL construction logic accordingly. Key changes include:
- Removing the redundant isHttps() helper and using the URL.protocol property instead.
- Adding support for window.__STREAMLIT_BACKEND_URL and window.__STREAMLIT_HOST_CONFIG_BACKEND_URL so that static assets and server requests can target different origins.
- Updating tests and related utilities to support the new URL configuration flows.
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/utils/src/uri/index.ts | Refactored buildHttpUri to use protocol from URL and removed the isHttps() helper. |
| frontend/utils/src/uri/index.test.ts | Updated tests to pass the protocol property instead of relying on isHttps(). |
| frontend/lib/src/util/utils.ts | Modified the extraction of pathname using a passed pathname instead of document.location. |
| frontend/connection/src/utils.ts | Refactored base URI functions to support optional configurable backend URL in window. |
| frontend/connection/src/utils.test.ts | Updated tests to reflect changes made to URL building functions and added tests for getBaseUriParts. |
| frontend/connection/src/types.ts | Declared new global window variables for backend configuration. |
| frontend/connection/src/WebsocketConnection.test.tsx | Updated test mocks to include protocol field for URI objects. |
| frontend/connection/src/DoInitPings.tsx | Updated host config URI construction to read from window.__STREAMLIT_HOST_CONFIG_BACKEND_URL. |
| frontend/connection/src/DefaultStreamlitEndpoints.test.ts | Updated mock server URI definitions to include the protocol property. |
| frontend/app/src/App.tsx | Added conditionals and TODO comments to handle cases when window.__STREAMLIT_BACKEND_URL is set. |
Comments suppressed due to low confidence (1)
frontend/connection/src/DoInitPings.tsx:130
- Consider adding validation or error handling when parsing window.__STREAMLIT_HOST_CONFIG_BACKEND_URL. An invalid URL from this global variable could break the host configuration URI construction.
const hostConfigServerUriParts = window.__STREAMLIT_HOST_CONFIG_BACKEND_URL ? getBaseUriParts(window.__STREAMLIT_HOST_CONFIG_BACKEND_URL) : uriParts
lukasmasuch
left a comment
There was a problem hiding this comment.
LGTM 👍 Added a couple of nits above.
0b1ee90 to
a81841d
Compare
## Describe your changes In #11378, we left some TODOs to come back and fix page URL handling for multipage apps in the world where we configure the client to hit a different origin for the Streamlit server from the one that we fetched our `index.html` from. This PR addresses these issues by defining a new `MAIN_PAGE_BASE_URL` field in the `__streamlit` object which lets us explicitly specify what the base URL for the document (that is, the URL of the main page of the app) should be. Note that this change will also make it possible to fix the annoying issue where initial healthcheck requests hit a 404 when navigating directly to a subpage of a multipage app in the pure OSS world, but we don't do so in this PR as it'll also require us to change how our static asset handler works to no longer serve a truly static `index.html` but dynamically set some pieces of it, which would take a nontrivial amount of additional effort. ## Testing Plan - Unit Tests (JS and/or Python) - Adjusted JS unit tests --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license. --------- Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]>
Describe your changes
In some new (Snowflake-internal) deployments of Streamlit, we want to be able to configure an
app to load its
index.htmlfrom one origin but make requests to a Streamlit server at another.This PR enables this by reading the
window.__STREAMLIT_BACKEND_BASE_URLandwindow.__STREAMLIT_HOST_CONFIG_BASE_URLvariables and sending requests meantfor the Streamlit server to those URLs if the variables are set. Otherwise, we continue to assume
that the server can be reached at
window.location.hrefas usual.The
index.htmlserved by this deployment will then be modified to set these variables in<script>tags to configure these URLs.This may also eventually be useful more generally by the Open Source community in some scenarios
where an app developer, for example, wants to serve the static assets of their app from a CDN while
hosting their Streamlit server at a different origin, but we'll need to make improvements to our
documentation + provide some additional tooling before we can consider this broadly supported.
Note that:
isHttpshelper function since it's redundant on topof the
protocolfield that's already set when parsing a URL.window.__STREAMLIT_BACKEND_BASE_URLis set, we currently expect there to be some weirdnessthat happens with multipage apps and the browser's forward/back buttons, but given this behavior isn't
exposed unless you're changing Streamlit internals, and since fixing this will require some thought, we punt
on it for now.
Testing Plan
Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.