From 42067e077b404f4ca6f002ade273d55a3dec8616 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Tue, 18 Dec 2018 16:14:20 -0800 Subject: [PATCH] [RfC] Fix URL too long (#6519) When a URL gets too long (usually happens with controls that allow free form text), it creates an array of bugs. * bug when creating a short URL, because the POST request's referrer field is too long * a bug when saving a chart (when the modal shows up) also because of the referrer being too long Some work has been done in the past to mitigate this, and I'm unclear if it's some sort of regression because of the Flask upgrade or some browser change, or whether these bugs have always been around. This is a request for comment on an approach that works. Let me know if you can think of better ideas as to how to manage this. My current solution looks for 8000+ characters URLs and shrinks them to only `/superset/explore/?URL_IS_TOO_LONG_TO_SHARE&form_data=...` and we only keep the formData keys for `datasource` and `viz_type`. Not super elegant but does the trick. --- .../components/ExploreViewContainer.jsx | 2 +- superset/assets/src/explore/exploreUtils.js | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/superset/assets/src/explore/components/ExploreViewContainer.jsx b/superset/assets/src/explore/components/ExploreViewContainer.jsx index 162cb16333..ae52a0b46d 100644 --- a/superset/assets/src/explore/components/ExploreViewContainer.jsx +++ b/superset/assets/src/explore/components/ExploreViewContainer.jsx @@ -171,7 +171,7 @@ class ExploreViewContainer extends React.Component { addHistory({ isReplace = false, title }) { const { payload } = getExploreUrlAndPayload({ formData: this.props.form_data }); - const longUrl = getExploreLongUrl(this.props.form_data); + const longUrl = getExploreLongUrl(this.props.form_data, null, false); try { if (isReplace) { history.replaceState(payload, title, longUrl); diff --git a/superset/assets/src/explore/exploreUtils.js b/superset/assets/src/explore/exploreUtils.js index 4eac3abce4..e9bcc9ff70 100644 --- a/superset/assets/src/explore/exploreUtils.js +++ b/superset/assets/src/explore/exploreUtils.js @@ -2,6 +2,8 @@ import URI from 'urijs'; import { availableDomains } from '../utils/hostNamesConfig'; +const MAX_URL_LENGTH = 8000; + export function getChartKey(explore) { const slice = explore.slice; return slice ? (slice.slice_id) : 0; @@ -40,7 +42,7 @@ export function getURIDirectory(formData, endpointType = 'base') { return directory; } -export function getExploreLongUrl(formData, endpointType) { +export function getExploreLongUrl(formData, endpointType, allowOverflow = true, extraSearch = {}) { if (!formData.datasource) { return null; } @@ -48,11 +50,23 @@ export function getExploreLongUrl(formData, endpointType) { const uri = new URI('/'); const directory = getURIDirectory(formData, endpointType); const search = uri.search(true); + Object.keys(extraSearch).forEach((key) => { + search[key] = extraSearch[key]; + }); search.form_data = JSON.stringify(formData); if (endpointType === 'standalone') { search.standalone = 'true'; } - return uri.directory(directory).search(search).toString(); + const url = uri.directory(directory).search(search).toString(); + if (!allowOverflow && url.length > MAX_URL_LENGTH) { + const minimalFormData = { + datasource: formData.datasource, + viz_type: formData.viz_type, + }; + return getExploreLongUrl( + minimalFormData, endpointType, false, { URL_IS_TOO_LONG_TO_SHARE: null }); + } + return url; } export function getExploreUrlAndPayload({