Grails Resources, 302s, SSL, and Chrome - javascript

Grails 2.1.1 with the resources plugin.
I'm using the jstree library and it utilizes themes. You specify a theme name in the config:
"themes":{
"theme":"default",
"dots":false,
"icons":true
}
And the JavaScript finds it relative to the library's path. That means the URL is built and is relative, then gets added to the document. For example, it might look like:
/a/js/jsTree/themes/default/styles.css
I have the following in my ApplicationResources.groovy:
tree {
resource url: '/js/jsTree/1.0/_lib/jquery.cookie.js'
resource url: '/js/jsTree/1.0/_lib/jquery.hotkeys.js'
resource url: '/js/jsTree/1.0/jquery.jstree.js'
}
When I deploy this on our server with SSL, on Firefox and Safari, I see the that styles.css being 302'd to the static path that the resources plugin does.
/a/static/js/jsTree/themes/default/styles.css
And then that new path is pulled in, and I can see it is coming over SSL. However, in Chrome I see the 302 and then the new URL is trying to stream over non-SSL and Chrome is blocking it (silently even) so the tree styles do not render at all, which obviously makes it unusable.
Sorry, but I cannot at this time make an example of this problem that anyone can publicly view. I'm hoping someone else might have ran into this situation before.

The issue ended up being something with jsTree. I changed the config to include the URL instead of letting jsTree figure it out:
"themes":{
"theme":"default",
"dots":false,
"icons":true,
"url": contextPath + "/js/jsTree/1.0/themes/default/style.css"
}

Related

Getting JSON from a website with no visible files using p5.js

I am trying to import a json file from a website using p5.js, and i thought it would be quite easy, however when i tried it i realized the json was actually just in plain text on the page (It is the only thing on the page). I checked chrome web tools to look at index.html, but i was greeted by "(index)", is it a problem with google or am i just going to have to use something else than this?
function preload() {
httpGet('leaderboard.popcat.click', 'json', function(response) {
});
}
//there are the setup and draw functions aswell
I got an error when i ran the code aswell, it was
Error: JSONP request to url failed
here is a picture of the page btw, (the url is leaderboard.popcat.click)
EDIT: The main problem i am having is that there is no file in https://leaderboard.popcat.click/, not the getting of json.
The network tab says no such url exists, and i believe that is because of the fact that i didn't specify a file.
Here is the console output aswell
I solved my issue by starting chrome in no-cors mode or whatever it's called AND using the full path of the website. I got it into no-cors mode by making a shortcut with this link
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir=~/chromeTemp"
and running it as an administrator

wasm/dotnet Integrity attribute invalid for my Blazor app on Github pages

See the error on my website here
I have embedded a blazor app in my jekyll site. It runs perfectly locally, but when I publish it on github pages, I am getting this error:
Failed to find a valid digest in the 'integrity' attribute for resource 'https://chrisevans9629.github.io/blazor/xt/_framework/wasm/dotnet.3.2.0-rc1.20222.2.js' with computed SHA-256 integrity 'yVt8FYsTQDifOGsifIkmEXwe+7ML0jZ1dMi2xluiDXQ='. The resource has been blocked.
This is something that I think blazor generates when the page is ran. this is what my page looks like that starts blazor:
<script src="js/index.js"></script>
<app>Loading...</app>
Built with <3 using Blazor
<script src="_framework/blazor.webassembly.js"></script>
This is what the page looks like on github pages:
<script src="js/index.js"></script>
<app>Loading...</app>
<p>Built with <3 using Blazor
<script src="_framework/blazor.webassembly.js"></script></p>
<script type="text/javascript">var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;</script><script src="_framework/wasm/dotnet.3.2.0-rc1.20222.2.js" defer="" integrity="sha256-iZCHkFXJWYNxCUFwhj+4oqR4fkEJc5YGjfTTvdIuX84=" crossorigin="anonymous"></script></body>
Why is this error happening and how can I fix this? I've thought about create a script that would remove the integrity attribute, but I don't think that would be a good solution.
I found an answer here
Cause
Because I am using github pages to host my blazor app, it's using git to push up the code. Git by default will try to normalize line endings when committing code, which was causing the integrity of the blazor app to fail due to the files changing.
Solution
To fix this, I added a .gitattributes file to my blazor folder with * binary as the contents.
This tells git to treat all files as binary and therefore not to normalize the line endings. After I did that, I had to delete my _framework folder in my blazor app and rebuild it. After doing this, the blazor app worked.
In case someone else ends up here with the issue I had today..
I also got this error on a Blazor Wasm app locally after simple modification, and then still appeared after reverting changes.
The solution for me was to do a clean and rebuild.
In my case, it was a wrong target framework in the publish profile - I should not have selected win-x64.
I'm not sure of the exact reason, but the server interferes in some way with the response, based on the target framework. Just select browser-wasm and redeploy; it should be fine.
I spent too much time on this issue. Clean and Rebuild does not work for me.
What worked for me is deleting bin and obj folders from the Client(Blazor WASM) Project.
Environment
.Net 5 and 6
Visual Studio 2019 and 2022
Just to leave here a note on something I came across while trying to figure out what was going on.
If for some reason you removed the service worker from your app and the resources were actually cached in the common http cache, there is a possibility that once you re-enable the service worker you will get this error, because the service worker will pick up the http cached version and not the server's.
What I did was to add cache: "no-cache" to the Request's init.
So my onInstall now looks something like this
async function onInstall(event) {
console.info('Service worker: Install');
// Fetch and cache all matching items from the assets manifest
const assetsRequests = self.assetsManifest.assets
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: "no-cache" }));
// Also cache authentication configuration
assetsRequests.push(new Request('_configuration/TestApp.Client'));
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
}
It looks like hash generated inside ServiceWorkerAssetsManifest for all the files and on the client side don't match. It looks like ServiceWorkerAssetsManifest is not generating hash again when the file is modified, specially the static files.
Had the same problem today, in my case the error came with a css file.
The problem was that I had two versions of my application deployed to local folders.
At first I started the old version, closed it and then opened up the new version.
It seems that the old css file was cached in the browser which caused the error to appear.
The fix was simply pressing CTRL + U to open up the index.html file, clicking on the css file which caused the error and press F5 to reload the file. This solved the error for me.
A better solution!
Open service-worker.js
change
.map(asset => new Request(asset.url, { integrity: asset.hash }));
to :
.map(asset => new Request(asset.url));
Now it works!
I Had this same issue and none of these solutions worked for me, but they set me on the right path. I am deploying mine to my local machine and using IIS for testing purposes, and I found that in the publish profile that I have created in Visual Studio 2022, the check box to "Remove additional files at destination" was not checked and as soon as I checked this and republished it, everything worked fine. I must have removed a file that was being published in a previous build and it was still there since it wasn't being deleted by any subsequent builds/publishes. But this solved it for me, it might

How to circumvent browser caching? [duplicate]

Is there a way I can put some code on my page so when someone visits a site, it clears the browser cache, so they can view the changes?
Languages used: ASP.NET, VB.NET, and of course HTML, CSS, and jQuery.
If this is about .css and .js changes, then one way is "cache busting" by appending something like "_versionNo" to the file name for each release. For example:
script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.
or after the file name:
script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.
You can check this link to see how it could work.
Look into the cache-control and the expires META Tag.
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">
Another common practices is to append constantly-changing strings to the end of the requested files. For instance:
<script type="text/javascript" src="main.js?v=12392823"></script>
Update 2012
This is an old question but I think it needs a more up to date answer because now there is a way to have more control of website caching.
In Offline Web Applications (which is really any HTML5 website) applicationCache.swapCache() can be used to update the cached version of your website without the need for manually reloading the page.
This is a code example from the Beginner's Guide to Using the Application Cache on HTML5 Rocks explaining how to update users to the newest version of your site:
// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the new hotness.
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}, false);
See also Using the application cache on Mozilla Developer Network for more info.
Update 2016
Things change quickly on the Web.
This question was asked in 2009 and in 2012 I posted an update about a new way to handle the problem described in the question. Another 4 years passed and now it seems that it is already deprecated. Thanks to cgaldiolo for pointing it out in the comments.
Currently, as of July 2016, the HTML Standard, Section 7.9, Offline Web applications includes a deprecation warning:
This feature is in the process of being removed from the Web platform.
(This is a long process that takes many years.) Using any of the
offline Web application features at this time is highly discouraged.
Use service workers instead.
So does Using the application cache on Mozilla Developer Network that I referenced in 2012:
Deprecated This feature has been removed from the Web standards.
Though some browsers may still support it, it is in the process of
being dropped. Do not use it in old or new projects. Pages or Web apps
using it may break at any time.
See also Bug 1204581 - Add a deprecation notice for AppCache if service worker fetch interception is enabled.
Not as such. One method is to send the appropriate headers when delivering content to force the browser to reload:
Making sure a web page is not cached, across all browsers.
If your search for "cache header" or something similar here on SO, you'll find ASP.NET specific examples.
Another, less clean but sometimes only way if you can't control the headers on server side, is adding a random GET parameter to the resource that is being called:
myimage.gif?random=1923849839
I had similiar problem and this is how I solved it:
In index.html file I've added manifest:
<html manifest="cache.manifest">
In <head> section included script updating the cache:
<script type="text/javascript" src="update_cache.js"></script>
In <body> section I've inserted onload function:
<body onload="checkForUpdate()">
In cache.manifest I've put all files I want to cache. It is important now that it works in my case (Apache) just by updating each time the "version" comment. It is also an option to name files with "?ver=001" or something at the end of name but it's not needed. Changing just # version 1.01 triggers cache update event.
CACHE MANIFEST
# version 1.01
style.css
imgs/logo.png
#all other files
It's important to include 1., 2. and 3. points only in index.html. Otherwise
GET http://foo.bar/resource.ext net::ERR_FAILED
occurs because every "child" file tries to cache the page while the page is already cached.
In update_cache.js file I've put this code:
function checkForUpdate()
{
if (window.applicationCache != undefined && window.applicationCache != null)
{
window.applicationCache.addEventListener('updateready', updateApplication);
}
}
function updateApplication(event)
{
if (window.applicationCache.status != 4) return;
window.applicationCache.removeEventListener('updateready', updateApplication);
window.applicationCache.swapCache();
window.location.reload();
}
Now you just change files and in manifest you have to update version comment. Now visiting index.html page will update the cache.
The parts of solution aren't mine but I've found them through internet and put together so that it works.
For static resources right caching would be to use query parameters with value of each deployment or file version. This will have effect of clearing cache after each deployment.
/Content/css/Site.css?version={FileVersionNumber}
Here is ASP.NET MVC example.
<link href="#Url.Content("~/Content/Css/Reset.css")?version=#this.GetType().Assembly.GetName().Version" rel="stylesheet" type="text/css" />
Don't forget to update assembly version.
I had a case where I would take photos of clients online and would need to update the div if a photo is changed. Browser was still showing the old photo. So I used the hack of calling a random GET variable, which would be unique every time. Here it is if it could help anybody
<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...
EDIT
As pointed out by others, following is much more efficient solution since it will reload images only when they are changed, identifying this change by the file size:
<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"
A lot of answers are missing the point - most developers are well aware that turning off the cache is inefficient. However, there are many common circumstances where efficiency is unimportant and default cache behavior is badly broken.
These include nested, iterative script testing (the big one!) and broken third party software workarounds. None of the solutions given here are adequate to address such common scenarios. Most web browsers are far too aggressive caching and provide no sensible means to avoid these problems.
Updating the URL to the following works for me:
/custom.js?id=1
By adding a unique number after ?id= and incrementing it for new changes, users do not have to press CTRL + F5 to refresh the cache. Alternatively, you can append hash or string version of the current time or Epoch after ?id=
Something like ?id=1520606295
<meta http-equiv="pragma" content="no-cache" />
Also see https://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images
Here is the MDSN page on setting caching in ASP.NET.
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True
If Response.Cache.VaryByParams("Category") Then
'...
End If
Not sure if that might really help you but that's how caching should work on any browser. When the browser request a file, it should always send a request to the server unless there is a "offline" mode. The server will read some parameters like date modified or etags.
The server will return a 304 error response for NOT MODIFIED and the browser will have to use its cache. If the etag doesn't validate on server side or the modified date is below the current modified date, the server should return the new content with the new modified date or etags or both.
If there is no caching data sent to the browser, I guess the behavior is undetermined, the browser may or may not cache file that don't tell how they are cached. If you set caching parameters in the response it will cache your files correctly and the server then may choose to return a 304 error, or the new content.
This is how it should be done. Using random params or version number in urls is more like a hack than anything.
http://www.checkupdown.com/status/E304.html
http://en.wikipedia.org/wiki/HTTP_ETag
http://www.xpertdeveloper.com/2011/03/last-modified-header-vs-expire-header-vs-etag/
After reading I saw that there is also a expire date. If you have problem, it might be that you have a expire date set up. In other words, when the browser will cache your file, since it has a expiry date, it shouldn't have to request it again before that date. In other words, it will never ask the file to the server and will never receive a 304 not modified. It will simply use the cache until the expiry date is reached or cache is cleared.
So that is my guess, you have some sort of expiry date and you should use last-modified etags or a mix of it all and make sure that there is no expire date.
If people tends to refresh a lot and the file doesn't get changed a lot, then it might be wise to set a big expiry date.
My 2 cents!
I implemented this simple solution that works for me (not yet on production environment):
function verificarNovaVersio() {
var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
$.ajax({
url: "./versio.txt"
, dataType: 'text'
, cache: false
, contentType: false
, processData: false
, type: 'post'
}).done(function(sVersioFitxer) {
console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
location.reload(true);
}
});
}
I've a little file located where the html are:
"versio.txt":
v00.5.0014
This function is called in all of my pages, so when loading it checks if the localStorage's version value is lower than the current version and does a
location.reload(true);
...to force reload from server instead from cache.
(obviously, instead of localStorage you can use cookies or other persistent client storage)
I opted for this solution for its simplicity, because only mantaining a single file "versio.txt" will force the full site to reload.
The queryString method is hard to implement and is also cached (if you change from v1.1 to a previous version will load from cache, then it means that the cache is not flushed, keeping all previous versions at cache).
I'm a little newbie and I'd apreciate your professional check & review to ensure my method is a good approach.
Hope it helps.
In addition to setting Cache-control: no-cache, you should also set the Expires header to -1 if you would like the local copy to be refreshed each time (some versions of IE seem to require this).
See HTTP Cache - check with the server, always sending If-Modified-Since
There is one trick that can be used.The trick is to append a parameter/string to the file name in the script tag and change it when you file changes.
<script src="myfile.js?version=1.0.0"></script>
The browser interprets the whole string as the file path even though what comes after the "?" are parameters. So wat happens now is that next time when you update your file just change the number in the script tag on your website (Example <script src="myfile.js?version=1.0.1"></script>) and each users browser will see the file has changed and grab a new copy.
Force browsers to clear cache or reload correct data? I have tried most of the solutions described in stackoverflow, some work, but after a little while, it does cache eventually and display the previous loaded script or file. Is there another way that would clear the cache (css, js, etc) and actually work on all browsers?
I found so far that specific resources can be reloaded individually if you change the date and time on your files on the server. "Clearing cache" is not as easy as it should be. Instead of clearing cache on my browsers, I realized that "touching" the server files cached will actually change the date and time of the source file cached on the server (Tested on Edge, Chrome and Firefox) and most browsers will automatically download the most current fresh copy of whats on your server (code, graphics any multimedia too). I suggest you just copy the most current scripts on the server and "do the touch thing" solution before your program runs, so it will change the date of all your problem files to a most current date and time, then it downloads a fresh copy to your browser:
<?php
touch('/www/sample/file1.css');
touch('/www/sample/file2.js');
?>
then ... the rest of your program...
It took me some time to resolve this issue (as many browsers act differently to different commands, but they all check time of files and compare to your downloaded copy in your browser, if different date and time, will do the refresh), If you can't go the supposed right way, there is always another usable and better solution to it. Best Regards and happy camping. By the way touch(); or alternatives work in many programming languages inclusive in javascript bash sh php and you can include or call them in html.
For webpack users:-
I added time with chunkhash in my webpack config. This solved my problem of invalidating cache on each deployment. Also we need to take care that index.html/ asset.manifest is not cached both in your CDN or browser. Config of chunk name in webpack config will look like this:-
fileName: [chunkhash]-${Date.now()}.js
or If you are using contenthash then
fileName: [contenthash]-${Date.now()}.js
This is the simple solution I used to solve in one of my applications using PHP.
All JS and CSS files are placed in a folder with version name. Example : "1.0.01"
root\1.0.01\JS
root\1.0.01\CSS
Created a Helper and Defined the version Number there
<?php
function system_version()
{
return '1.0.07';
}
And Linked JS and SCC Files like below
<script src="<?= base_url(); ?>/<?= system_version();?>/js/generators.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?= base_url(); ?>/<?= system_version(); ?>/css/view-checklist.css" />
Whenever I make changes to any JS or CSS file, I change the System Verson in Helper and rename the folder and deploy it.
I had the same problem, all i did was change the file names which are linked to my index.html file and then went into the index.html file and updated their names, not the best practice but if it works it works. The browser sees them as new files so they get redownloaded on to the users device.
example:
I want to update a css file, its named styles.css, change it to styless.css
Go into index.html and update , and change it to
in case interested I've found my solution to get browsers refreshing .css and .js in the context of .NET MVC (.net fw 4.8) and the use of bundles.
I wanted to make browsers refresh cached files only after a new assembly is deployed.
Buinding on Paulius Zaliaduonis response, my solution is as follows:
store your application base url in the web config app settings (the HttpContext is not yet available at runtime during the RegisterBundle...), then make this parameter changing according to the configuration (debug, staging, release...) by the xml transform
In BundleConfig RegisterBundles get the assembly version by the means of reflection, and...
...change the default tag format of both styles and scripts so that the bundling system generates link and script tags appending a query string parameter on them.
Here is the code
public static void RegisterBundles(BundleCollection bundles)
{
string baseUrl = system.Configuration.ConfigurationManager.AppSettings["by.app.base.url"].ToString();
string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Styles.DefaultTagFormat = $"<link href='{baseUrl}{{0}}?v={assemblyVersion}' rel='stylesheet'/>";
Scripts.DefaultTagFormat = $"<script src='{baseUrl}{{0}}?v={assemblyVersion}'></script>";
}
You'll get tags like
<script src="https://example.org/myscriptfilepath/script.js?v={myassemblyversion}"></script>
you just need to remember to to build a new version before deploying.
Ciao
Do you want to clear the cache, or just make sure your current (changed?) page is not cached?
If the latter, it should be as simple as
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

html5 appcache adding/removing specific files

Say I have a simple appcache manifest that looks like:
CACHE:
# v1
# images
images/one.jpg
images/two.jpg
images/three.jpg
I then use some server side method to update the manifest to:
CACHE:
# v1
# images
images/one.jpg
images/two.jpg
images/three.jpg
images/four.jpg
And then call a function client side to update the appcache:
function updateCache(){
var appCache = window.applicationCache;
appCache.update();
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache();
}
}
I would like to 'add' my new image to the existing cache without downloading everything again (which is what's currently happening). Is this possible or am I missing something fundamental?
It will download everything again, that's the way it's designed to work. However if you have set far future expiry headers on your images then the chances are the browser will fetch them from the local browser cache rather than requesting them off the server again.
Note that if you do this during development this can lead to some strange behaviour, but you should definitely do it for production sites.

Problem While Doing html5 webapp cache

I have a webapp which has the domain http://draft.mo2do.com
when i am accessing the url it will resolve like the below url and redirect to the corresponding site home page
http://draft.mo2do.com/s/_91665/Home
Here i implemented offline cache. My cache.manifest file is the below
CACHE MANIFEST
# Offline cache v4.0
# All other resources (e.g. sites) require the user to be online.
NETWORK:
*
# Additional resources to cache CACHE:
# Add the pages in to the cache
/s/_91665/Home /s/_91665/CachedDraftBoard
http://draft.mo2do.com
# Add the images in to the cache
/s/store/-1/webapp/styles/webapp.css
/s/store/-1/webapp/styles/nba_draft.css
/s/store/-1/webapp/styles/add2drafthome.css?v2
# Add the js files in to the cache
/s/store/-1/webapp/scripts/jquery-1.5.min.js
/s/store/-1/webapp/scripts/iscroll.js
/s/store/-1/webapp/scripts/webapp.js
/s/store/-1/webapp/scripts/nba_draft.js
/s/store/-1/webapp/scripts/cacheUpdate.js
/s/store/-1/webapp/scripts/add2drafthome.js?v0.9.4
/webapp/icon.png /webapp/startup.png
/s/store/-1/webapp/nba/addtodrafthome/arrow.png
/s/store/-1/webapp/nba/addtodrafthome/close-bubble.png
/s/store/-1/webapp/nba/addtodrafthome/icon.png
/s/store/-1/webapp/nba/addtodrafthome/plus.png
/s/store/-1/webapp/nba/addtodrafthome/share.png
FALLBACK:
http://draft.mo2do.com
If i am directly accessing the site url the caching is working and that time i didnt mention the "http://draft.mo2do.com" in the cache section.During this time offline cache is working fine.
If i directly access only the domain url "http://draft.mo2do.com" in the browser it is not opening 404 in the offline mode.
Then i added the "http://draft.mo2do.com" in the cache section that time i am getting exception
Application Cache Progress event (2 of 3) http://draft.mo2do.com/ Application Cache Error event: Resource fetch failed (-1) http://draft.mo2do.com/
If i access the domain also it should load the app in the offline mode. If i access direct url app is loading fine.
How can I solve this issue?
The cache has to directly reference specific resources, be they Javascript, CSS, HTML pages, images, whatever. From what I can tell from the content above, you've done that. Simply placing a domain in there however won't work (you also need to reference all of the pages you want off-line, e.g. /s/_91665/Home needs to be in there).
So, there's an error somewhere along the line, but it's hard to figure out what you mean by this:
If i directly access only the domain url "http://draft.mo2do.com" in the browser it is not opening 404 in the offline mode.
Can you be more clear? Do you mean that going to that URL results in a 404, or is there something in the page itself that's in error?
Are you sure that your cache file is functioning as intended? If there are any errors at all in your cache file, your off-line application simply won't work. This page offers some debugging code which may help:
Debugging HTML 5 Offline Application Cache

Categories