In the 'default' case in drupal_get_js appends a cache-busting query string to URLs in an attempt to get browsers to reload pages when page caches are updated. This is fine, except for the fact that URLs added by modules may already have query-strings as part of the URI.
For instance, when using the Gallery module and navigating to the Gallery plugin management page, this URI is added via drupal_add_js():
/index.php?q=gallery&g2_view=core.CombinedJavascript&g2_key=cd60d0c257ddd99cc07f4efafd8004b0
drupal_get_js() appends "?1207482595". Since the URI above already has a query-string, the ? should be replaced with a &.
In some circumstances, this usage of ? instead of & causes actual breakage because the webserver chooses to disregard all of the query parameters after the first ? and only acknowledges the ones after the second ?.
Attached is a patch which will test the URL before appending the query string and determine which parameter should be used.
| Comment | File | Size | Author |
|---|---|---|---|
| #25 | 243251_2.patch | 6.6 KB | naxoc |
| #21 | 243251_1.patch | 6.61 KB | naxoc |
| #19 | 243251.patch | 6.51 KB | naxoc |
| #11 | 243251_query_string.patch | 2.48 KB | mcarbone |
| #8 | screenshot3.jpg | 187.7 KB | sodafox |
Comments
Comment #1
Signe commentedApply the same logic to drupal_get_css(). I haven't seen an issue here, yet, but it's begging for it to occur.
Comment #2
sun+1
Arbitrary query strings can also break certain JavaScripts, for example TinyMCE, as mentioned in http://drupal.org/node/218296#comment-810963
The workaround for now is to set the $cache parameter to FALSE -- however, this results in browsers not caching the JavaScript at all.
So, in addition to those patches here, we badly need a way to force no query string at all for certain drupal_add_js() calls.
Marking as critical.
Comment #3
wretched sinner - saved by grace commentedI also came across this issue in Drupal 6 - see #242875: No way to disable 'cachebuster' query-string appended to CSS file links.. Have marked that as a duplicate of this one.
Comment #4
jcsiegrist commentedThis issue also breaks language pack loading for the tinyMCE module. The Language packs javascript url returns a drupal 404 error, thus the javascript is never loaded. This should be patched for drupal 6.x as well.
Comment #5
sunBugs are fixed in HEAD first.
Comment #6
lilou commentedReroll for D7.
Comment #7
sunFor D7, I'd suggest to allow developers to pass
$options = array('query' => FALSE)in the new $options array to disable the query string for certain JS files only.Also, this issue unfortunately seems to deal with two issues:
a) Original poster: Drupal's query string is not properly added to an existing query string, i.e.
myfile.js?arg1=value?B. There are two ? in the resulting URL. The original poster needs a way to properly assign a query string, f.e.b) Drupal's query string breaks the execution of certain scripts, i.e.
myfile.js?B, is sufficient to break the execution of certain scripts (perhaps in specific browsers only, dunno). Since setting the 'cache' option to FALSE results in yet another query string ($info['cache'] ? $query_string : '?' . REQUEST_TIME), there should be an option for developers to disable Drupal's query cache string for certain scripts only, f.e.Comment #8
sodafox commentedI seem to have the same problem. I'm new to drupal and all the lingo. Here's a screen shot that explains what I get when I try to upload an image using Tinymce and the wysiwygAPI. I also had the same result when trying to get Image assist to work without the error messages displayed.
Also I've managed to get simple patches working before but I'm having trouble understanding which lines to add or remove on this one.
Comment #9
sunBugs are fixed in the current development branch first.
@sodafox: Also, please do not change issue classification. The bug you are experiencing seems to be limited to using Wysiwyg API and Image Assist. If you were experiencing the bug of *this* issue, neither TinyMCE nor Image Assist would show up at all. Please file a new issue in Image Assist's queue (but search for existing issues first). Thanks.
Comment #10
sunBetter title. Point 2) of my last summary was already fixed elsewhere.
Comment #11
mcarbone commentedRe-rolled to keep up with HEAD.
Comment #12
creslin commentedI concur - this is not useful at all.
First it's obfuscated, most developers who
* write file.css
* add file.css to theme.info
Expect file.css to be called from the browser - not file.css?[a-z]
Secondly this has silently bust our mod_deflate in Apache for all CSS's served - meaning 10x the bandwidth and latency implicit in downloading a larger file.
Third, content switching above Drupal hosts to pull css/media from a.another server is now bust - all content is being served from our dynamic host. I simply cannot configure our Layer5 Load balancers to manage a ? in the GET to determine which server to get the data from.
How do I switch this madness off.
- Cres
Comment #13
mcarbone commentedI think you misunderstand this thread. It's not to add the ability to turn off query parameters completely, but to fix a bug when an included file already includes a query parameter. If you want to add an option to disable that functionality completely, I suggest you create a new issue.
Comment #14
sun.core commented#11: 243251_query_string.patch queued for re-testing.
Comment #15
sun.core commentedRTBC if bot passes, please.
Comment #16
wretched sinner - saved by grace commentedBased on @sun above
Comment #17
sunActually, I was mistaken and meant another patch in the queue, but this one looks good, too. ;)
Comment #18
webchickWe should get some tests for this. This is the very definition of something we will easily break in the future trying to "optimize" this part of the code and not notice when the regression is introduced.
Comment #19
naxoc commentedI wrote a small test that checks that css and js files with an appended querystring will display correctly in the inclusions.
When I ran the test I saw that locale got upset with urls that have an appended query string when it is translating js files, so I fixed that.
I also had to do some alterations to the patch because of #228818: IE: Stylesheets ignored after 31 link/style tags. I had to put a
check_plain()on the file inclusion on @import css rules. I am not sure that is cool, but it works. I did some research on whether @import should display urls escaped or not. I did not really find anything, but it is considered good practice that link tags escapes urls, so I figured the same was true for @import.Comment #20
sun$qs_sep still needs a proper variable name.
In comments and messages, CSS should always be uppercase.
Ditto for JS. Additionally, we don't abbreviate JavaScript (note the special casing)
Ditto.
Unless I overlooked something, this string is not used by tests, so we should just return an empty string here.
139 critical left. Go review some!
Comment #21
naxoc commentedReroll with changes from review :)
Comment #22
sun1 of 3 doesn't use check_plain() though - any not-so-obvious reason for that?
139 critical left. Go review some!
Comment #23
naxoc commentedYou are right, it is not so obvious...
The js one that does not use check_plain is
drupal_get_js(). That function usestheme_html_tag, that callsdrupal_attributesand that runscheck_plain.I wonder if it is OK that it is the responsibility of the theming layer to use check_plain?
Comment #24
damien tournoud commentedMore precisely, it seems that this check_plain() is unnecessary, and will lead to double encoding:
Comment #25
naxoc commentedThat is so true. I removed the checkplain on the link that is going in for theming with
theme_html_tagComment #26
sunLooks good to me.
Comment #27
dries commentedCommitted to CVS HEAD. Thanks.
Comment #28
wretched sinner - saved by grace commentedBased on Dries' comment above...
Comment #29
pwolanin commentedprobably needs to be backported.
Comment #30
david strauss@creslin
That's a configuration problem on your end:
This also sounds like a configuration issue.
Comment #31
jimrockford commentedThis might help someone attempting to use Google Closure in Drupal. I'm still on Drupal 6.14. I was trying to use drupal_add_js to source base.js from Google's closure library. Like all other such calls to include JS, Drupal appended "?s" to the filename (i.e.,
/base.js?s). The result was that none of my goog.require() statements were working. Any code referencing google closure library vars resulted in undefined. Basically, base.js seemed to NOT be downloaded, and so goog namespace was unknown and then all goog.require() calls failed. Only when I added the lines shown below directly in head of page.tpl.php (sans the "?s" appended to the filename), and quit using drupal_add_js() for closure JS files, did closure start working and all the undefined errors went away.
With my page.tpl.php customized like this, my desired google closure code started working:
Comment #32
dpearcefl commentedIs there any interest in this issue? Has this issue been fixed in the latest D6?
Comment #33
sunI don't think this will be backported.
Comment #34
aaronbaumanThis is still broken for drupal_add_js with type "file".
file_create_url() url encodes the javascript item's "data" property, breaking the url if it includes a query string.
Works fine for "external" javascripts.
The test included in the patch above was simplified to remove the js's query string by #829822-25: Check Drupal 7 core for vulnerabilities in SA-CONTRIB-2010-066, in 2d3af8fe.