Classic ASP cache busting (& yet still satisfying PageSpeed score) - caching

Scenario:
I am working with IIS and ASP, and we need to cache the site (to make Google Page Speed, and my boss, happy). We currently have IIS caching everything (asp/JS/CSS) for a period of 1 week.
Problem:
After updating the HTML content on the ASP pages, my boss sees the old version of the page until he does a (force) refresh.
Question:
How can I (force) update the server cache after I make a change to the ASP HTML content?
I would like my peers and managers to see the latest changes without making them do a forced browser refresh.

Are you configured to use the "If-Modified-Since" HTTP Header?
This explanation on Scott Hanselman's blog gives you and idea of what you are looking for - Forcing an update of a cached JavaScript file in IIS
This page also provides a useful primer for the "If-Modified-Since" HTTP Header

Let's see if we can make the boss happy. Like you, I have a few people that think F5 or Ctrl+F5 is annoying.
Quick Review, to be sure your Output Cache on your IIS server is updating on Change let's set it to "Cache until Change".
I read that you clear it every week but if things don't change... Why?
Let's set the client browser caching defaults.
And you have the following for all your page headers letting the page expire after 30 minutes using GMT time.
Master header:
Dim dtmExp
Response.Buffer = True
Response.CharSet = "UTF-8"
dtmExp = DateAdd("n", 30, Now())
Response.ExpiresAbsolute = dtmExp
Response.Expires = dtmExp
We have several options and methods to trigger our header change.
You can use Sessions, Cookies, DB updates etc. in this example I'm using Sessions feel free to change things around to fit your application better.
PageEdit.asp
Session("EditedPageFullURL") = "/yourpage.asp"
In a common functions page add the following.
Function EditorsReload(eChk,erURL)
If IsNumeric(eChk) Then
Session("Editing") = eChk
End If
If Len(erURL) = 0 Then
Exit Function
End If
If Session("Editing") <> "" Then
If Session("Editing") = 1 Then
If (LCase(erURL) = LCase(Request.ServerVariables("SCRIPT_NAME"))) Then
Session("Editing") = ""
Session("EditedPageFullURL") = ""
Response.Expires = -1
Response.ExpiresAbsolute = Now() -1
Response.AddHeader "pragma", "no-store"
Response.AddHeader "cache-control","no-store, no-cache, must-revalidate"
End If
End If
End If
End Function
Place the following in your page just below any headers you might have.
Call EditorsReload(1,Session("EditedPageFullURL"))
You can wrap it in a "Session("AUTH")" if your site has login and member sessions setup.
Other than that, this will fire only when Session("EditedPageFullRUL" has a length greater than 1.
This will update the bosses browser header forcing the browser to refresh the local cache.
It is a one time deal so any additional page refresh is using the standard headers.
There are many ways of doing this so be creative!

Related

varnish cache real (body) size vs content-length

Sometimes, when an object is not in the cache, varnish will send an object that has a real size smaller than the size declared in the content-length header. For example - only part of the picture.
Is it possible to construct such a rule...?
if (beresp.http.content-lenght <> real_object_body_size) { return(retry); }
I wrote a script that tests the same request against the varnish and the backend. It compares the downloaded size with the content-lenght header. The backend, unlike varnish, sometimes ends up with a timeout but the size is always fine. The problem is rare but annoying because the objects are set to long user cache time.
After a few days I can say that the problem was in occasional backend problems with varnish's ability to send a chunked transfer if the object is not in the cache.
Thank you #Thijs Feryn for pointing this out. I knew about that property but until I read it here, I didn't connect it to my problem at all.
It seems that "set beresp.do_stream = false;" solved the problem.

Drupal 9 - custom module caching issue

Longtime D7 user, first time with D9. I am writing my first custom module and having a devil of a time. My routing calls a controller that simple does this:
\Drupal::service('page_cache_kill_switch')->trigger();
die("hello A - ". rand());
I can refresh the page over and over and get a new random number each
time. But, when I change the code to:
\Drupal::service('page_cache_kill_switch')->trigger();
die("hello B - ". rand());
I still get "hello A 34234234" for several minutes. Clearing the cache doesn't help, all I can do is wait, it's normally about two minutes. I am at my wits end.
I thought it maybe an issue with my docker instance. So I generated a simple HTML file but if I edit then reload that file changes are reflected immediately.
In my settings.local.php I have disabled the render cache, caching for migrations, Internal Page Cache, and Dynamic Page Cache.
In my mymod.routing.yml I have:
options:
_admin_route: TRUE
no_cache: TRUE
Any hint on what I am missing would be deeply appreciated.
thanks,
summer

Drupal 7 ignoring $_SESSION in template

I'm working on a simple script in a custom theme in Drupal 7 that is supposed to just rotate through different background image each time a user loads the page. This is my code in [view].tpl.php that picks which image to use.
$img_index = (!isset($_SESSION["img_index"]) || is_null($_SESSION["img_index"])) ? 1 : $_SESSION["img_index"] + 1;
if ($img_index > 2) {
$img_index = 0;
}
$_SESSION["img_index"] = $img_index;
Pretty simple stuff, and it works fine as long as Drupal starts up a session. However, if I delete my session cookie, then always shows the same image, a session is never started.
I'm assuming that since this code is in the view file that the view code is being cached for anonymous users and hence the session is never started, but I can't figure out how to otherwise do what I want.
Don't mess with session like /u/maiznieks mentioned on Reddit. It's going to affect performance.
I've had to do something similar in the past and went with an approach like /u/maiznieks mentions. It's something like this,
Return all the URLs in an array via JS on Drupal.settings.
Check if a cookie is set.
If it's not, set it and set it's value to 0.
If it's set, get the value, increase the value by one, save it to the cookie.
With that value, now you have an index.
Check if image[index] exists
If it does, show that to the user.
If it doesn't, reset index to 0 and show that. Save 0 to the cookie.
You keep caching. You keep showing the user new images on every page load.
You could set your current view to do a random sort every 5 mins. You would then only have to update the logic above to replace that image. That way you can keep something similar working for users with no JS but still keep this functionality for the rest.
You can replace cookies above with HTML5 local storage if you'd like.
#hobberwickey, I will suggest to create a custom module and implement hook_boot() in module. As per drupal bootstrap process session layer will call after cache layer everytime. hook_boot can be called in cache pages and before bootstrap process also. You can take more information here.

Is there a way to view the HttpRuntime.Cache?

I have a webservice that stores an authenticated users token in the HttpRuntime.Cache to be used on all subsequent requests. The cached item has a sliding expiration on it of 24 hours.
Secondly I have a vb.net app that is pinging this webservice every 15 seconds. It gets authenticated once, then uses the cached token for all subsequent requests. My problem is that the application appears to lose authentication at random intervals of time less than the 24 hr sliding expiration. However with it getting pinged every 15 sec the authentication should never expire.
I am looking for a way to view the HttpRuntime.cache to try and determine if the problem is in the webservice security methods or within the vb.net app. Can I view the HttpRuntime.cache somehow?
The webservice is part of a web forms site that was built with asp.net 2.0 on a Windows Server 2008.
The name of my key's were unknown as they were system generated guid values with a username as the value. So in order to view a cache collection that was unknown I used a simple loop as follows.
Dim CacheEnum As IDictionaryEnumerator = Cache.GetEnumerator()
While CacheEnum.MoveNext()
Dim cacheItem As String = Server.HtmlEncode(CacheEnum.Entry.Key.ToString())
Dim cacheItem2 As String = Server.HtmlEncode(CacheEnum.Entry.Value.ToString())
Response.Write(cacheItem & ":" & cacheItem2 & "<br />")
End While
Hope this helps others.
First off, HttpRuntime.Cache would not be the best place to store user authentication information. You should instead use HttpContext.Current.Session to store such data. Technically the cache is allowed to "pop" things in it at its own will (whenever it decides to).
If you actually need to use the cache, you can check if your item is in the cache by simply doing:
HttpRuntime.Cache["Key"] == null

Custom session variables persisting after deletion

I'm having a bit of trouble with Drupal 7 and removing session variables I've set.
Things work as expecting when adding an item (via: $_SESSION['products']['p123'] = 'my product') and then removing (via: unset($_SESSION['products']['p123']) ) - which would leave me with an empty$_SESSION['products'] array.
But when I attempt to add another item (such as $_SESSION['products']['pABC'] = 'another product'), I would suddenly have both 'p123' and 'pABC' as keys in my $_SESSION['products'] array, even after the initial deletion of 'p123'.
Do I have to explicitly tell Drupal 7 that I've deleted an item out of my SESSIONS and to save that change? I hadn't had this issue using Drupal 6.
Turns out this was because of shifting from HTTP to HTTPS.
I was making my additions on a page served over HTTP, and my deletions on a page served by HTTPS. It seems that drupal keeps separate session variables for both secure and insecure connections, and will push the insecure session to secure when that transition is made.

Resources