Varnish - PURGE request does not purge hash_data() URL - varnish

In vcl_hash, I have
backend default {
.host = "127.0.0.1";
.port = "8080";
}
acl purge {
"localhost";
}
sub vcl_hash {
if(req.http.Cookie ~ "isLogin") {
hash_data("1");
}
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
return (lookup);
}
return(lookup);
}
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in Cache.";
}
}
I am using below command to purge urls.
curl -X PURGE http://release.com/user/details
If url is cached for logged-out users, I get below output
curl -X PURGE http://release.com/user/details
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>200 Purged.</title>
</head>
<body>
<h1>Error 200 Purged.</h1>
<p>Purged.</p>
<h3>Guru Meditation:</h3>
<p>XID: 1071483546</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
If it is cached only for logged-in users, I keep getting below output. (Even though url is making "Hits")
curl -X PURGE http://release.com/user/details
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>404 Not in Cache.</title>
</head>
<body>
<h1>Error 404 Not in Cache.</h1>
<p>Not in Cache.</p>
<h3>Guru Meditation:</h3>
<p>XID: 998719206</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
http://release.com/user/details looks different on the basis if user is logged in or not. (ie it has isLogin cookie or not). PURGE is not working for urls that were hashed in vcl_hash.
Seems to be an error or feature of Varnish. Please suggest, what can be done.

I figured out the problem in my case probably it's the same for you and anyone using vcl_hash with purge. The hash is used for the purge so all the request information used for the has hash to be present for doing the purge. In your case you checking the cookie if(req.http.Cookie ~ "isLogin") so you must send this cookie with the purge request like:
curl -X PURGE --cookie "isLogin=1" http://release.com/user/details
If you want to purge all variants of the hash you'll need to call it twice, once with the cookie and once without.

We have a similar scenario. We want to serve different content to mobile & desktop users (depending on the User-Agent).
We are doing it without changing the object hash. We are using different variants (Vary) of the same object. Read the cache invalidation documentation.
We are using a custom header that is added in the beresp.http.Vary (we also use this custom header in our backend).
In our scenario, it is mandatory to set the Vary header that is sent back to the users (including Google) so they know that the response depends on the User-Agent. We do it in vcl_deliver.
sub vcl_recv {
...
if (req.restarts == 0) {
# Change this code, we are using a CloudFront header
if (req.http.CloudFront-Is-Mobile-Viewer == "true") {
set req.http.X-Device-Type = "mobile";
} else {
set req.http.X-Device-Type = "desktop";
}
}
...
if (req.method == "PURGE") {
if (!client.ip ~ acl_purge) {
return(synth(400, "Bad request."));
}
return(purge);
}
...
}
sub vcl_backend_response {
...
if (beresp.http.Vary) {
set beresp.http.Vary = beresp.http.Vary + ", " + "X-Device-Type";
} else {
set beresp.http.Vary = "X-Device-Type";
}
...
}
sub vcl_deliver {
...
set resp.http.Vary = "Accept-Encoding, User-Agent";
...
}

Related

Twig show source code but not HTML

I'm trying to run Twig (standalone, without Symfony 2) in a PHP project (Wamp) but it doesn't work : Twig shows the templates source code but does not execute the HTML. I don't find why. Here is my code :
index.php:
// DOCUMENT_ROOT (constant defined in a previous included file) : C:/Program Files/wamp/www/project
$sTwigPath = DOCUMENT_ROOT."/vendors/twig/lib/Twig/Autoloader.php";
if (file_exists($sTwigPath)) {
require($sTwigPath);
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(DOCUMENT_ROOT."/templates");
$tpl = new Twig_Environment($loader, array("cache"=>false));
try {
$oTemplate = $tpl->loadTemplate("home.html");
} catch (Twig_Error_Loader $e) {
error_log("Twig library not found", 0);
exit;
}
$aRender = array();
$aRender["myVar"] = "Wouah! myVar is displayed here!";
echo $oTemplate->render($aRender);
home.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Home</h1>
{{myVar}}
</body>
</html>
I've no error (checked in PHP and apache logs).

ServiceStack Ignores Accept Header

Any reason why ServiceStack would ignore the Accept header? The service is hosted in a ASP.NET app and running in debug within the IDE. The first 40 or so calls to the service, using a System.Web.WebRequest object causes the service to respond correctly. After approximately 50 calls a 404 error is detected by the client (breakpoint not hit in the service). From that point forward, the Accept header is ignored. All subsequent requests always return XML.
The client being used...
var client = (HttpWebRequest)WebRequest.Create(uri);
client.Method = WebRequestMethods.Http.Post;
client.AllowWriteStreamBuffering = false;
client.SendChunked = true;
client.ContentType = "multipart/form-data;";
client.Timeout = int.MaxValue; // HACK:REMOVE
client.Accept = "application/json";
The call is a bit messy right now (trying to debug the failure)...
using (FileStream fileStream = File.OpenRead(filePaths[i]))
{
fileStream.Copy(client.GetRequestStream());
}
var responseString = string.Empty;
try { responseString = new StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (String.IsNullOrWhiteSpace(responseString)) { continue; }
PutFileResponse response = null;
try { response = responseString.FromJson<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
try { response = responseString.FromXml<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
continue;
}
}
I left this as-is to show the the response. The first 50 (approx) calls return JSON as requested. After the 404 all subsequent calls always return XML.
Any thoughts?
Edit (2014-02-25 10:35 EST):
After looking at Fiddler this is a bit more odd than I had thought. Of 559 requests, 34 of them result in 404 errors. However the service continues to respond both before and after the error without issue. The 404 error is the first puzzling part. The second item (the switch between XML and JSON is a bit less puzzling but strange nonethless.
The app is a file storage app and is recursing a test directory to push files to the service. Some of the files it is encountering are actual XML files. All files are sent in a Stream, nested in a DTO, with the client adding an Accept header for "application/json" for each request. If an XML file is sent, even though the Accept header has been sent, the service responds with XML.
Example Request Header (session 94):
POST
http://localhost:50205/Files/Put/8178F94DBDBC4AB18F42118AFD01D1A2/AA10C004D624DA892171F8A7E8CD8D05/201760/ServiceStack.xml HTTP/1.1
Content-Type: multipart/form-data;
Accept: application/json
Host: localhost:50205
Transfer-Encoding: chunked
Expect: 100-continue
1000
<?xml version="1.0"?>
<doc>
[SNIP]
</doc>
0
Example Response Header (session #94):
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/xml
Server: Microsoft-IIS/8.0
X-Powered-By: ServiceStack/4.011 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcX1NvdXJjZVxGSUwwMVx0cnVua1xTcG90bGVzc1xGcmFtZXdvcmtzXEZpbGVNYW5hZ2VtZW50XFByb2plY3RzXEZNRi5TdG9yYWdlU2VydmVyLkhvc3RpbmcuUHVibGljXEZpbGVzXFB1dFw4MTc4Rjk0REJEQkM0QUIxOEY0MjExOEFGRDAxRDFBMlxBQTEwQzAwNEQ2MjREQTg5MjE3MUY4QTdFOENEOEQwNVwyMDE3NjBcU2VydmljZVN0YWNrLnhtbA==?=
X-Powered-By: ASP.NET
Date: Tue, 25 Feb 2014 15:19:06 GMT
Content-Length: 563
<?xml version="1.0" encoding="utf-8"?><PutFileResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FMF.StorageServer.Services.Messages.Files"><ResponseStatus xmlns:d2p1="http://schemas.servicestack.net/types" i:nil="true" /><Status><FileSignature><Checksum>AA10C004D624DA892171F8A7E8CD8D05</Checksum><SizeBytes>201760</SizeBytes></FileSignature><IsAvailable i:nil="true" /><IsKnown i:nil="true" /><IsOnDisk i:nil="true" /><IsSuccessful i:nil="true" /><StatusMessage i:nil="true" /></Status></PutFileResponse>
The unfortunate part of this is that I would have to detect the inner structure of every file before sending it to the server and could never trust the file extension. Either that or always assume that the server might decide to send back XML when I didn't expect it.
A more pressing concern would be why the 404 errors are being detected for only SOME of the requests. In 559 requests, the items producing a 404 error are 77, 232, 235, 238, 246, 275, etc... so the service or client is just failing on random requests.
Edit (2014-02-25 12:20 EST):
It appears as if ALL of the files that failed (404 error) were text-based. For example...
Example Request Header (session #560):
POST http://localhost:50205/Files/Put/060C976372174F51BEB84FE524E57C57/1931975CE8E1090A6D66738A560888AD/1426/AssemblyInfo.cs HTTP/1.1
Content-Type: multipart/form-data;
Accept: application/json
Host: localhost:50205
Transfer-Encoding: chunked
Expect: 100-continue
592
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Utility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Utility")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1071992e-2d4c-49df-9526-6d4d29f979b4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
0
Example Response Header (session #560):
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B?RDpcX1NvdXJjZVxGSUwwMVx0cnVua1xTcG90bGVzc1xGcmFtZXdvcmtzXEZpbGVNYW5hZ2VtZW50XFByb2plY3RzXEZNRi5TdG9yYWdlU2VydmVyLkhvc3RpbmcuUHVibGljXEZpbGVzXFB1dFwwNjBDOTc2MzcyMTc0RjUxQkVCODRGRTUyNEU1N0M1N1wxOTMxOTc1Q0U4RTEwOTBBNkQ2NjczOEE1NjA4ODhBRFwxNDI2XEFzc2VtYmx5SW5mby5jcw==?=
X-Powered-By: ASP.NET
Date: Tue, 25 Feb 2014 15:24:10 GMT
Connection: close
Content-Length: 5106
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 8.0 Detailed Error - 404.7 - Not Found</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 5px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;word-break:break-all;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px;
font-weight:bold;font-size:1em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif;
color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF;
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal;
font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;}
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;}
-->
</style>
</head>
<body>
<div id="content">
<div class="content-container">
<h3>HTTP Error 404.7 - Not Found</h3>
<h4>The request filtering module is configured to deny the file extension.</h4>
</div>
<div class="content-container">
<fieldset><h4>Most likely causes:</h4>
<ul> <li>Request filtering is configured for the Web server and the file extension for this request is explicitly denied.</li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Things you can try:</h4>
<ul> <li>Verify the configuration/system.webServer/security/requestFiltering/fileExtensions settings in applicationhost.config and web.config.</li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Detailed Error Information:</h4>
<div id="details-left">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Module</th><td> RequestFilteringModule</td></tr>
<tr><th>Notification</th><td> BeginRequest</td></tr>
<tr class="alt"><th>Handler</th><td> ServiceStack.Factory</td></tr>
<tr><th>Error Code</th><td> 0x00000000</td></tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Requested URL</th><td> http://localhost:50205/Files/Put/060C976372174F51BEB84FE524E57C57/1931975CE8E1090A6D66738A560888AD/1426/AssemblyInfo.cs</td></tr>
<tr><th>Physical Path</th><td> D:\_Source\FIL01\trunk\Spotless\Frameworks\FileManagement\Projects\FMF.StorageServer.Hosting.Public\Files\Put\060C976372174F51BEB84FE524E57C57\1931975CE8E1090A6D66738A560888AD\1426\AssemblyInfo.cs</td></tr>
<tr class="alt"><th>Logon Method</th><td> Not yet determined</td></tr>
<tr><th>Logon User</th><td> Not yet determined</td></tr>
<tr class="alt"><th>Request Tracing Directory</th><td> C:\Users\Fred\Documents\IISExpress\TraceLogFiles\FMF.STORAGESERVER.HOSTING.PUBLIC</td></tr>
</table>
<div class="clear"></div>
</div>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>More Information:</h4>
This is a security feature. Do not change this feature unless the scope of the change is fully understood. If the file extension for the request should be allowed, remove the denied file extension from configuration/system.webServer/security/requestFiltering/fileExtensions.
<p>View more information »</p>
</fieldset>
</div>
</div>
</body>
</html>
Edit (2014-02-25 14:27 EST):
Continuing to test and finding that ServiceStack ignoring the Accept header IS a bigger problem than I hoped. Since all files must be persisted, and since those files must include both HTML and XML files, I need to ensure ServiceStack only sends back the response that was requested. Some of the files sent in my last test included HTML files and, quite unfortunately, ServiceStack sent back an HTML document as the response.
The temp folder contains a bunch of random files. And, as you might expect, because I have a ton of source files on hand, the temp folder includes a few C#/VS2K12 solutions. For example, I copied in the source of DoFactory's solution and several of its .Config, .cs, .csproj files fail while others of the same type go through.
The DTO being used...
//[Route("/Files/Put/{Token}/{Checksum}/{SizeBytesText}/{FileNameOrExtension}", "POST")]
[Route("/Files/Put/{PathInfo*}", "POST")]
public class PutFileRequest : IReturn<PutFileResponse>, IRequiresRequestStream
{
public string Token { get; set; }
public string Checksum { get; set; }
public string SizeBytesText { get; set; }
public string FileNameOrExtension { get; set; }
public System.IO.Stream RequestStream { get; set; }
}
I've intentionally included the original route I was using. Note that the URI is constructed using a set of variables and the name of the file. The name of the file is used for convenience on the server to allow the file to be persisted using the original file extension.
Below is the Main method from a test app which fails consistently. Any attempt to post this file will cause a 404 error. Note that the file is intact and that the FileSteam is able to open and copy the contents of the file successfully. Had a problem existed with the file then this should have failed.
static void Main(string[] args)
{
var filePath = #"D:\Temp\_Source\DoFactory\CS_4.5\Spark\Art.Web\Areas\Shop\Models\ProductsModel.cs";
var fileInfo = Files.GetInfo(filePath, calculateChecksum: true);
var uri = #"http://localhost:50205/Files/Put/" +
Guid.NewGuid().ToString("N") + "/" +
fileInfo.Checksum + "/" +
fileInfo.SizeBytes.Value + "/" +
System.IO.Path.GetFileName(filePath);
var client = (HttpWebRequest) WebRequest.Create(uri);
client.Method = WebRequestMethods.Http.Post;
client.AllowWriteStreamBuffering = false;
client.SendChunked = true;
client.ContentType = "multipart/form-data;";
client.Timeout = int.MaxValue;
client.Accept = "application/json";
using (FileStream fileStream = File.OpenRead(filePath))
{
fileStream.CopyTo(client.GetRequestStream());
}
var responseString = string.Empty;
try { responseString = new StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (String.IsNullOrWhiteSpace(responseString)) { Environment.Exit(1); }
PutFileResponse response = null;
try { response = responseString.FromJson<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
try { response = responseString.FromXml<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
if (response == null)
{
try { response = responseString.FromJsv<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
if (response == null) { Environment.Exit(2); }
Console.ReadLine();
}
After a day+ of testing, and somewhere around 1,000 tests, I have found a way around the problem. However, in the findings leave me with a request to the ServiceStack team to find a way around this.
If a file is posted to a path which appears to contain a file name at the end, ServiceStack will respond with a result matching the contents of the item contained within the RequestStream. If the item is HTML the response will be an HTML response. If the item is XML the response will be an XML response. In these scenarios the Accept header is always ignored.
To navigate around this problem I have broken the filename into separate parts within the URL. A path that would originally resolve as:
http://localhost:1234/Files/Put/ABC123/MyFile.xml
... is now posting as this ...
http://localhost:1234/Files/Put/ABC123/F/MyFile/X/xml
... or, if I just need the extension, the parts of the extension are broken ...
http://localhost:1234/Files/Put/ABC123/X/tar/gz
In these examples, the service knows how to reassemble the file name and/or extension.
The end result to this change is that XML and HTML files are posted, as expected, and ServiceStack obeys the Accept header. In all tests after this change ServiceStack responded with the needed JSON object. Additionally, no 404 errors are encountered.

Codeigniter page shows 404 page not found

I am new to codeIgniter and Linux as well. When I tried to run http://localhost/CodeIgniter/hello/first_page it shows 404 Error: Page not found. My Controller class :
/*hello.php*/
class Hello extends CI_Controller
{
function __construct() {
parent::__construct();
}
function first_page()
{
$this->load->view('first_view');
}
}
And my first_view.php is :
<html>
<head>
<title>First CI Page</title>
</head>
<body>
Hi Folks !
</body>
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
?>
</html>
NB: http://localhost/CodeIgniter shows the welcome message.And all files are executable(777)
Try this url.. You'll get it
http://localhost/CodeIgniter/index.php/hello/first_page
You have to include index.php

Is it possible to check if cookies are enabled with modernizr?

I was researching about how to check if the cookies are enabled in a browser and i found a lot of answer, i even tested a few ones, but after that a friend of mine suggest me to use Modernizr for that.
I started to search about that and i found a lot of stuff related with CSS3 and HTML5, but i don't want that, i just wanna know if is it possible to check that cookies are enabled or not with Modernizr?
check this url, hope it's helpful :
https://github.com/Modernizr/Modernizr/commit/33f00fbbeb12e92bf24711ea386e722cce6f60cc
Below code is copied from http://sveinbjorn.org/cookiecheck.
function are_cookies_enabled()
{
var cookieEnabled = (navigator.cookieEnabled) ? true : false;
if (typeof navigator.cookieEnabled == "undefined" && !cookieEnabled)
{
document.cookie="testcookie";
cookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false;
}
return (cookieEnabled);
}
A direct answer to the question is 'Yes!' and it is built in
Example code:
if (Modernizr.cookies == false) {
alert('Please enable cookies');
}
else {
// do something with cookies
}
You can also use the css class .cookies or .no-cookies to show/hide a panel telling the user they need cookies enabled.
.cookies #noCookies
{
display: none;
}
<div id='#noCookies'>
This site requires cookies! Please turn them on already!
</div>
(This .cookies class is added to <body> tag by Modernizr).
Note: If you are creating a custom build of Modernizr the cookies option is currently 'hidden' under the 'Non-core detects' section.
Another way with PHP
HTML/PHP:
<?php
session_start();
$_SESSION['cook'] = 1;
echo "<img src=\"cookcheck.php\">";
?>
PHP - cookcheck.php:
<?php
session_start();
if ($_SESSION['cook'] !== 1)
{ $image="/nocookmsg.png"; } # Cookies NOT Enabled
else { $image="/blank.png"; } # Cookies Enabled
$img=imageCreateFromPNG($image); # Create Image
header("Content-type: image/png"); # Send Header
imagePNG($image); # Send Image
?>

browser back button doesnt work in cached environment

The back button just causes my page to refresh. Is there a way around this without disabling the cache?
Try adding this to your HTML header:
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
where you click on product/image on page there call onclick javascript function i.e.
function getHashOnBack(valueget)
{
location.hash = "#backTo=" + $(window).scrollTop();$(document).height();
}
Now, put
$(document).ready(function ()
{
var ab = window.location.hash.substring(1).split("=");
if (ab[0] == "backTo")
{
// this would be called automatically when back putton pressed and hav #back=1234 etc. // value in url
$(window).scrollTop(parseInt(ab[1]));
}
}

Resources