[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.
This commit is contained in:
Maxime Beauchemin 2018-12-18 16:14:20 -08:00 committed by GitHub
parent 5a1ff0f09d
commit 42067e077b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 3 deletions

View File

@ -171,7 +171,7 @@ class ExploreViewContainer extends React.Component {
addHistory({ isReplace = false, title }) { addHistory({ isReplace = false, title }) {
const { payload } = getExploreUrlAndPayload({ formData: this.props.form_data }); 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 { try {
if (isReplace) { if (isReplace) {
history.replaceState(payload, title, longUrl); history.replaceState(payload, title, longUrl);

View File

@ -2,6 +2,8 @@
import URI from 'urijs'; import URI from 'urijs';
import { availableDomains } from '../utils/hostNamesConfig'; import { availableDomains } from '../utils/hostNamesConfig';
const MAX_URL_LENGTH = 8000;
export function getChartKey(explore) { export function getChartKey(explore) {
const slice = explore.slice; const slice = explore.slice;
return slice ? (slice.slice_id) : 0; return slice ? (slice.slice_id) : 0;
@ -40,7 +42,7 @@ export function getURIDirectory(formData, endpointType = 'base') {
return directory; return directory;
} }
export function getExploreLongUrl(formData, endpointType) { export function getExploreLongUrl(formData, endpointType, allowOverflow = true, extraSearch = {}) {
if (!formData.datasource) { if (!formData.datasource) {
return null; return null;
} }
@ -48,11 +50,23 @@ export function getExploreLongUrl(formData, endpointType) {
const uri = new URI('/'); const uri = new URI('/');
const directory = getURIDirectory(formData, endpointType); const directory = getURIDirectory(formData, endpointType);
const search = uri.search(true); const search = uri.search(true);
Object.keys(extraSearch).forEach((key) => {
search[key] = extraSearch[key];
});
search.form_data = JSON.stringify(formData); search.form_data = JSON.stringify(formData);
if (endpointType === 'standalone') { if (endpointType === 'standalone') {
search.standalone = 'true'; 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({ export function getExploreUrlAndPayload({