"Re open last closed tab" causing to show last ajax request content - javascript

I am using HTML 5 history api to save state when ajax requests happen and i provide full html content if user request to same page with none ajax request.
"Re-open last closed tab" feature of browser brings last ajax request content without hitting to server. If browser would request without bring last request content then everything would work without problem. But browser just show last ajax request content.
I have been experienced this on Chrome 17, Firefox 10. (i haven't tried it on ie9 because it has no support history api)
What is well-known solution for this problem ?
Edit: These ajax requests are just "get" request to server.
it is really not possible to demonstrate it in jsfiddle.net because few reasons. You can demonstrate it in your localhost like below.
Make "get" request to server and pull json objects then push that url into history api like below.
history.pushState(null,null,url);
Then close that tab and click "Re-open last closed tab" feature of your browser. What do you see ? Json response body ? Browser shows it without making request to server, right ?

Problem was causing by http response headers. Headers was contain cacheable information for ajax requests so browser was showing that url content from cache without hit to database.
After removing cache params from response headers then browser was able to hit server without brings content from cache.

When you reopen a closed tab, the browser is allowed to reuse the data from cache for the given URL to populate the window. Since the data in cache is from the ajax request response, that's what it uses, and you see the JSON.
So that leads to the question: Why didn't the browser use the HTML from cache when satisfying the ajax request? Browsers use different rules to determine whether to use cached content depending on what they're doing. In this case, it appears Chrome is happy to reuse it when restoring the recently-closed tab, and not when doing the ajax request.
You can correct it by telling the browser to never cache the response. Whether that's desirable depends on your use case.
For instance, inserting these at the top of your file (after the opening <?php tag, of course) makes it not happen for me:
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

It all depends which browser you are using, and which optimisations are enabled.
Google Chrome for instance will keep the page in memory, so when you hit back and it goes to a new site, or when you do re-open closed tab - it will restore the page from memory.
Older/slower browsers will just refresh anything.
Though this shouldn't really be a problem, as your javascript state should be restored as well - it should be exactly the same in every way when they re-open that page.

Related

Why directive templates sometimes are loaded from server (with 304 response) and sometimes from browser cache (no request at all)?

When I reload page, Angular directive templates are loaded in two ways.
First one - browser makes a request to the server and it responses with 304 - it's ok.
But the second one - browser doesn't make a request. And I can't guess why.
As a result, when I make changes in templates from the first group, the changes are shown with the next page reload. But the changes in templates from the second group are not shown. That's the trouble.
And the question is - how to make the browser send request to the server for each template?
It seems that in the response headers for templates there are no Cache-Control headers. In such case a browser will use a heuristic to decide for how long a response can be cached.
To solve your problem of having always fresh templates fetched in development. You can:
check "Disable cache" in developer tools
set a proper Cache-Control header for resources you care about i.e :
Cache-Control: no-cache
If you want to understand different behaviours triggered by various Cache-Control values I highly recommend this article by Ilya Grigorik.

Execution order of Http Response headers?

I saw this plugin which download files using Ajax and some other fallback techniques.
But since ajax download file feature is not supported in all browsers , he used a trick with Iframe. ( which is pretty easy to implement)
But one thing caught my eye :
He also added an option which tells you when the file has finished
download.
He did it via cookie. He polls to see if the cookie via setInterval. as long as the cookie does not exist - the file wasn't finish download.( and when the cookie is present - the file has downloaded)
So the header for downloading a file is:
Content-Disposition: attachment; filename=Report0.pdf
And he added :
Set-Cookie: fileDownload=true; path=/
But then I thought - who said that set-cookie is called after the file has finish downloaded ?
Questions:
Looking at the actual headers :
1 - Does the browser digest each header according to the actual order of appearance ?
2 - Are there any headers which must appear prior to other headers ?
3 - Does the digest of each header - blocks the digest until current hedare digest is completed ? I mean : does the line content-disposition:attachment;filename=1.jpg prevents the browser from digesting the next header - until the filename=1.jpg is finished loading ?
nb
I've also tried investigate it via fiddler but I didn't get any conclusion.( I mean how can I test it in fiddler ?)
You're right to be skeptical.
There's no requirement that a client wait until the response body is complete to evaluate the Set-Cookie header that preceded the body, and there's in fact good reason to believe that most browsers will set the cookie before the body is complete (since many web pages will look at document.cookie in JavaScript inside a HTML page).
In fact, I tested this (using a MeddlerScript you can see here: http://pastebin.com/SUwCFyxS) and found that IE, Chrome and Firefox all set the cookie before the download completes, and set the cookie even if the user hits "Cancel" on the download.
The HTTP specification includes the notion of a Trailer (which is a header that appears after the response body) but these are little used and not supported in many clients (e.g. WinINET/IE). If the client did support Trailers, the server could send the Set-Cookie header after the body which would mean that the client couldn't see it until the body finished downloading.

Cause browser to revalidate (but not necessarily refetch) an image

In my web app we serve up all images with HTTP cache headers good for 24 hours, and also ETags. But sometimes the Javascript client app has cause to suspect that an image might have been updated. In those cases I would like to force the browser to revalidate the image cache, without actually breaking the cache.
For example, I get a user record (in JSON) which has a recent LastUpdated date on it. There are several possible reasons the LastUpdated date could have changed: the user might've changed their nickname, or joined a new board, or changed their image. So there's a good chance the image did not change, but we need to check.
I'm aware that I could re-request the image with a cache breaker appended to the URL. But that would force the image to reload whether it had changed or not, cause two entries in the browser's cache, and force me to update all my images with the new url. What I really want is to make the browser re-request the same URL, and send proper If-None-Match and/or If-Modified-Since headers in the request so that it will get a 304 if the image hasn't changed.
Is there any way to accomplish that in Javascript?
Since the image lives at the server, in a cache, the server is where the query needs to take place.
I would do a check before page load, force the server to renew the particular image in cache if needed. The "HTML" part should always assume all img-tags etc are correct.
Best ways of renewing single files in server cache is a different beast IMO.
This is actually rather simple to accomplish. Make an AJAX request for the image with the Cache-Control header set to max-age=0.
The server must respond with either the updated image (and a new set of cache headers), or with a 304 containing a Cache-Control header like public, max-age=123.
The 304 with a Cache-Control header is very important because it instructs the browser to update the freshness information associated with the resource.
When the request completes, remove the old <img> element from the DOM and reinsert a new one pointing to the same src.
This works because the request Cache-Control header tells the browser to ignore its cache and go to the network. When the browser gets a response back, it updates its cache – even though you don't actually do anything with the AJAX results.
Now when you remove the old element and insert a new one, the browser grabs the recently updated image directly from its cache.
In Chrome's network inspector, you see two requests: the AJAX request, then the request generated by reinserting the <img> element. However, if the server has set the Cache-Control headers properly, the second "request" is fulfilled by the browser's cache, and nothing is actually sent over the wire.
function updateImage(el) {
el = $(el);
var src = el.attr('src');
$.ajax({
url: src,
headers: {
'Cache-Control': 'max-age=0'
},
success: function() {
var parent = el.parent();
el.remove();
// this assumes that the <img> has no siblings and no attributes/classes/etc...
parent.append('<img>').attr('src',src);
}
});
}

Why serve 1x1 pixel GIF (web bugs) data at all?

Many analytic and tracking tools are requesting 1x1 GIF image (web bug, invisible for the user) for cross-domain event storing/processing.
Why to serve this GIF image at all? Wouldn't it be more efficient to simply return some error code such as 503 Service Temporary Unavailable or empty file?
Update: To be more clear, I'm asking why to serve GIF image data when all information required has been already sent in request headers. The GIF image itself does not return any useful information.
Doug's answer is pretty comprehensive; I thought I'd add in an additional note (at the OP's request, off of my comment)
Doug's answer explains why 1x1 pixel beacons are used for the purpose they are used for; I thought I'd outline a potential alternative approach, which is to use HTTP Status Code 204, No Content, for a response, and not send an image body.
204 No Content
The server has fulfilled the request
but does not need to return an
entity-body, and might want to return
updated metainformation. The response
MAY include new or updated
metainformation in the form of
entity-headers, which if present
SHOULD be associated with the
requested variant.
Basically, the server receives the request, and decides to not send a body (in this case, to not send an image). But it replies with a code to inform the agent that this was a conscious decision; basically, its just a shorter way to respond affirmatively.
From Google's Page Speed documentation:
One popular way of recording page
views in an asynchronous fashion is to
include a JavaScript snippet at the
bottom of the target page (or as an
onload event handler), that notifies a
logging server when a user loads the
page. The most common way of doing
this is to construct a request to the
server for a "beacon", and encode all
the data of interest as parameters in
the URL for the beacon resource. To
keep the HTTP response very small, a
transparent 1x1-pixel image is a good
candidate for a beacon request. A
slightly more optimal beacon would use
an HTTP 204 response ("no content")
which is marginally smaller than a 1x1
GIF.
I've never tried it, but in theory it should serve the same purpose without requiring the gif itself to be transmitted, saving you 35 bytes, in the case of Google Analytics. (In the scheme of things, unless you're Google Analytics serving many trillions of hits per day, 35 bytes is really nothing.)
You can test it with this code:
var i = new Image();
i.src = "http://httpstat.us/204";
First, i disagree with the two previous answers--neither engages the question.
The one-pixel image solves an intrinsic problem for web-based analytics apps (like Google Analytics) when working in the HTTP Protocol--how to transfer (web metrics) data from the client to the server.
The simplest of the methods described by the Protocol, the simplest (at lest the simplest method that includes a request body) is the GET request. According to this Protocol method, clients initiate requests to servers for resources; servers process those requests and return appropriate responses.
For a web-based analytics app, like GA, this uni-directional scheme is bad news, because it doesn't appear to allow a server to retrieve data from a client on demand--again, all servers can do is supply resources not request them.
So what's the solution to the problem of getting data from the client back to the server? Within the HTTP context there are other Protocol methods other than GET (e.g., POST) but that's a limited option for many reasons (as evidenced by its infrequent and specialized use such as submitting form data).
If you look at a GET Request from a browser, you'll see it is comprised of a Request URL and Request Headers (e.g., Referer and User-Agent Headers), the latter contains information about the client--e.g., browser type and version, browser langauge, operating system, etc.
Again, this is part of the Request that the client sends to the server. So the idea that motivates the one-pixel gif is for the client to send the web metrics data to the server, wrapped inside a Request Header.
But then how to get the client to Request a resource so it can be "tricked" into sending the metrics data? And how to get the client to send the actual data the server wants?
Google Analytics is a good example: the ga.js file (the large file whose download to the client is triggered by a small script in the web page) includes a few lines of code that directs the client to request a particular resource from a particular server (the GA server) and to send certain data wrapped in the Request Header.
But since the purpose of this Request is not to actually get a resource but to send data to the server, this resource should be a small as possible and it should not be visible when rendered in the web page--hence, the 1 x 1 pixel transparent gif. The size is the smallest size possible, and the format (gif) is the smallest among the image formats.
More precisely, all GA data--every single item--is assembled and packed into the Request URL's query string (everything after the '?'). But in order for that data to go from the client (where it is created) to the GA server (where it is logged and aggregated) there must be an HTTP Request, so the ga.js (google analytics script that's downloaded, unless it's cached, by the client, as a result of a function called when the page loads) directs the client to assemble all of the analytics data--e.g., cookies, location bar, request headers, etc.--concatenate it into a single string and append it as a query string to a URL (*http://www.google-analytics.com/__utm.gif*?) and that becomes the Request URL.
It's easy to prove this using any web browser that has allows you to view the HTTP Request for the web page displayed in your browser (e.g., Safari's Web Inspector, Firefox/Chrome Firebug, etc.).
For instance, i typed in valid url to a corporate home page into my browser's location bar, which returned that home page and displayed it in my browser (i could have chosen any web site/page that uses one of the major analytics apps, GA, Omniture, Coremetrics, etc.)
The browser i used was Safari, so i clicked Develop in the menu bar then Show Web Inspector. On the top row of the Web Inspector, click Resources, find and click the utm.gif resource from the list of resources shown on the left-hand column, then click the Headers tab. That will show you something like this:
Request URL:http://www.google-analytics.com/__utm.gif?
utmwv=1&utmn=1520570865&
utmcs=UTF-8&
utmsr=1280x800&
utmsc=24-bit&
utmul=enus&
utmje=1&
utmfl=10.3%20r181&
Request Method:GET
Status Code:200 OK
Request Headers
User-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/533.21.1
(KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
Response Headers
Cache-Control:private, no-cache, no-cache=Set-Cookie, proxy-revalidate
Content-Length:35
Content-Type:image/gif
Date:Wed, 06 Jul 2011 21:31:28 GMT
The key points to notice are:
The Request was in fact a request
for the utm.gif, as evidenced by the
first line above: *Request
URL:http://www.google-analytics.com/__utm.gif*.
The Google Analytics parameters are clearly visible in the query string
appended to the Request URL: e.g.,
utmsr is GA's variable name to refer to the client screen
resolution, for me, shows a value of
1280x800; utmfl is the variable
name for flash version, which has a
value of 10.3, etc.
The Response Header called
Content-Type (sent by the server back to the client) also confirms
that the resource requested and
returned was a 1x1 pixel gif:
Content-Type:image/gif
This general scheme for transferring data between a client and a server has been around forever; there could very well be a better way of doing this, but it's the only way i know of (that satisfies the constraints imposed by a hosted analytics service).
Some browsers may display an error icon if the resource could not load. It makes debugging/monitoring the service also a little bit more complicated, you have to make sure that your monitoring tools treat the error as a good result.
OTOH you don't gain anything. The error message returned by the server/framework is typically bigger then the 1x1 image. This means you increase your network traffic for basically nothing.
Because such a GIF has a known presentation in a browser - it's a single pixel, period. Anything else presents a risk of visually interfering with the actual content of the page.
HTTP errors could appear as oversized frames of error text or even as a pop-up window. Some browsers may also complain if they receive empty replies.
In addition, in-page images are one of the very few data types allowed by default in all broswers. Anything else may require explicit user action to be downloaded.
This is to answer the OP's question - "why to serve GIF image data..."
Some users will put a simple img tag to call your event logging service -
<img src="http://www.example.com/logger?event_id=1234">
In this case, if you don't serve an image, the browser will show a placeholder icon that will look ugly and give the impression that your service is broken!
What I do is, look for the Accept header field. When your script is called via an img tag like this, you will see something like following in the header of the request -
Accept: image/gif, image/*
Accept-Encoding:gzip,deflate
...
When there is "image/"* string in the Accept header field, I supply the image, otherwise I just reply with 204.
Well the major reason is to attach the cookie to it so if users go from one side to another we still have the same element to attach cookie to.
#Maciej Perliński is basically correct, but I feel a detailed answer will be beneficial.
why 1x1 GIF and not a 204 No-Content status code?
204 No-Content enables the server to omit all response headers (Content-Type, Content-Length, Content-Encoding, Cache-Control etc...) and return an empty response body with 0 bytes (and saving a lot of unneeded bandwidth).
Browsers know to respect 204 No-Content responses, and not to expect/wait for response headers and response body.
if the server needs to set any response header (e.g. cache-control or cookie), he cannot use 204 No-Content because browsers will ignore any response header by design (according to the HTTP protocol spec).
why 1x1 GIF and not a Content-Length: 0 header with 200 OK status code?
Probably a mix of several issues, just to name a few:
legacy browsers compatibility
MIME type checks on browsers, 0 bytes is not a valid image.
200 OK with 0 bytes might not be fully supported by intermediate proxy servers and VPNs
You don't have to serve an image if you are using the Beacon API (https://w3c.github.io/beacon/) implementation method.
An error code would work if you have access to the log files of your server. The purpose of serving the image is to obtain more data about the user than you normally would with a log file.

Submit cross domain ajax POST request

I swear I saw an article about this at one point but can not find it...
How can I perform a jQuery ajax request of type POST on another domain? Must be accomplished without a proxy. Is this possible?
Yes you can POST all you want, even $.post() works...but you won't get a response back.
This works, the other domain will get the POST:
$.post("http://othersite.com/somePage.php", { thing: "value" }, function(data) {
//data will always be null
});
But the response, data in the above example, will be null due to the same-origin policy.
All the options I've experimented with:
1) PORK: http://www.schizofreend.nl/Pork.Iframe/Examples/ Creates an iframe and submits the post there, then reads the response. Still requires same base domain per
request (i.e. www.foo.com can request
data from www2.foo.com, but not from
www.google.com) . Also requires you to
fiddle with the document.domain
property, which causes adverse side
effects. And there's a pervasive problem in all the major browsers where reloading the page basically shuffles the cached contents of all iframes on the page if any of them are dynamically written. Your response data will show up in the box where an ad is supposed to be.
2) flxhr: http://flxhr.flensed.com/ Can even be used to mask jQuery's built-in ajax so you don't even notice it. Requires flash though, so iPhone is out
3) jsonp: Doesn't work if you're posting a lot of data. boo.
4) chunked jsonp: When your jsonp request is too big, break the query string up into manageable chunks and send multiple get requests. Reconstruct them on the server. This is helpful but breaks down if you're load balancing users between servers.
5) CORS: http://www.w3.org/TR/cors/ doesn't work in older browsers (IE7, IE6, Firefox 2, etc)
So we currently do the following algorithm:
If request is small enough, use JSONP
If not small enough, but user has flash, use FlXHR
Else use chunked JSONP
Spend one afternoon writing that up and you'll be able to use it for good. Adding CORS to our algorithm might be good for faster iPhone support.
If you have control over the code running at the other domain, just let it return an appropriate Access-Control-Allow-Origin header in the response. See also HTTP Access-Control at MDC.
If you want a fire and forget POST where you don't care about the response then just submit a form to a hidden iframe. This requires a Transitional Doctype.
<form method="POST" action="http://example.com/" target="name_of_iframe">
If you want to parse the response, then using a proxy if the only real option.
If you are desperate, and control the remote site, then you can:
Submit a form as above
Set a cookie in the response (which might be blocked before the iframe could cause the cookie to be considered '3rd party' (i.e. likely to be advertising tracking).
Wait long enough for the response to come back
Dynamically generate a script element with the src pointing to the remote site
Use JSON-P in the response and take advantage of the data previously stored in the cookie
This approach is subject to race conditions and generally ugly. Proxing the data through the current domain is a much better approach.
If you need to know that the POST was successful, and don't have control over the remote server:
$.ajax({
type:"POST",
url:"http://www.somesite.com/submit",
data:'firstname=test&lastname=person&email=test#test.com',
complete: function(response){
if(response.status == 0 && response.statusText == "success")
{
/* CORS POST was successful */
}
else
{
/* Show error message */
}
}
});
If there was a problem with the submission then response.statusText should equal "error".
Note: some remote servers will send the HTTP header Access-Control-Allow-Origin: *, which will result in a 200 OK HTTP status code response. In that case, ajax will execute the success handler, and this method is not needed. To look at the response just do console.log(JSON.stringify(response)); or use FireBug's 'Net' panel.

Categories