Browser cache and HTTP protocol

Source: Internet
Author: User

There are several headers related to cache in http:
1. Pragma: Only the fixed no-Cache value can be used in HTTP/1.0 to disable browser cache.
2. Expires: Used to specify when the cached document is deemed to have expired, in GMT format. if the date is exceeded, the browser does not use local cache, but sends a new request like a server.
3. cache-control
No-Cache: disables browser and Proxy Server Caching. You can specify that some information headers are not cached separately. For example, no-Cache = set-Cookie does not cache cookie information.
No-store: the disk cannot be cached.
Max-age: after xx seconds, the document will be outdated and can replace expires. If both of them appear, Max-age takes precedence.
S-max-age: the validity period of the files cached on the Proxy Server
Must-revalidate: for client requests, the proxy server must verify to the server whether the cached documents are outdated and always get the latest documents to the client.
4. If-modified-since
When a client accesses a cached page, the file must be retrieved only after the page has been changed for a specified time.
If-modified-since is used to specify the time in GMT format.
5. Last-modified: The last update date of the document set by the server.
6. If-match: Define conditions for judging the expiration of a webpage
When the server sends a webpage to a client, it can pass the header field (etag) that represents the features of the object content. This header field is called an object tag. When the client sends a request to the server again,
If-match is used to carry OBJECT tag information.
7. etag: Tag information sent by the server to the client that represents the characteristics of the object content.
The following is an example of how these headers control the browser's cache format:
1. cache negotiation mechanism last-modified/if-modified-since
The browser caches the browsed pages. If the server tells the browser last-modified, when the browser visits the cached page next time, you can use if-modified-since to ask whether the server can use the local cache. If yes, the server will send a 304 status code.
However, if the server does not output the last-modified header field, the browser will not send the IF-modified-since header.
First, write a cacheservlet:
@ Webservlet (urlpatterns = {"/cacheservlet.html "})
Public class cacheservlet extends httpservlet {
@ Override
Protected void doget (httpservletrequest request, httpservletresponse response)
Throws servletexception, ioexception {
Response. setcontenttype ("text/html; charset = gb2312 ");
Printwriter out = response. getwriter ();
Out. Print ("Hello, cache! ");
Out. Close ();
}
}
Clear the browser cache and access http: // localhost: 8080/Cache/cacheservlet.html. The output is hello, cache!
Through httpwatch, you can see the request sent by the browser:
GET/Cache/cacheservlet.html HTTP/1.1
Accept: image/JPEG, application/X-MS-application, image/GIF, application/XAML + XML, image/pjpeg, application/X-MS-xbap, application/vnd. MS-Excel, application/vnd. MS-PowerPoint, application/MSWord ,*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
HOST: localhost: 8080
Connection: keep-alive
Response returned by the server:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:30:19 GMT

Hello, cache!
You can see that the server does not output the last-modified header field. Refresh the browser again and you can see the same result. The browser does not send if-modified-since. Open the browser cache:

We can see that the page cacheservlet.html has been saved. However, the "last modification time" is "NONE" and the "Deadline" is "NONE ". Therefore, no matter how refreshed, 200 is returned.
Next let's modify our Servlet and addLast-modifiedHeader:
@ Webservlet (urlpatterns = {"/cacheservlet.html "})
Public class cacheservlet extends httpservlet {
@ Override
Protected void doget (httpservletrequest request, httpservletresponse response)
Throws servletexception, ioexception {
Response. setcontenttype ("text/html; charset = gb2312 ");
Response. setdateheader ("last-modified", new date (). gettime ());
Printwriter out = response. getwriter ();
Out. Print ("Hello, cache! ");
Out. Close ();
}
}
Even if we clear the cache, restart tomcat, and access this page again,
Browser requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:33:09 GMT
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:33:09 GMT

Hello, cache!
We can see that the last-modified header is output this time, and then we can look at the cache:

The last modification was made this time, because the last-modified output by the server is in GMT format, and the browser displays the GMT zone. The difference between the two is exactly 8 hours.

This time we refresh the browser:
Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:33:09 GMT
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:34:29 GMT
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:34:29 GMT

Hello, cache!
Obviously, this client request carries the IF-modified-Since Header, but the server's default implementation is:
@ Override
Protected long getlastmodified (httpservletrequest req ){
Return super. getlastmodified (req );
}
This method returns-1 by default. Therefore, the server determines that the client cache has expired and returns 200.
For details, refer to the source code of httpservlet:
Protected void Service (httpservletrequest req, httpservletresponse resp)
Throws servletexception, ioexception {
String method = Req. getmethod ();
If (method. Equals (method_get )){
Long lastmodified = getlastmodified (req );
If (lastmodified =-1 ){
// Servlet doesn' t support if-modified-since, no reason
// To go through further expensive Logic
Doget (req, resp );
} Else {
Long ifmodifiedsince = Req. getdateheader (header_ifmodsince );
If (ifmodifiedsince <(lastmodified/1000*1000 )){
// If the servlet mod time is later, call doget ()
// Round down to the nearest second for a proper compare
// A ifmodifiedsince of-1 will always be less
Maybesetlastmodified (resp, lastmodified );
Doget (req, resp );
} Else {
Resp. setstatus (httpservletresponse. SC _not_modified );
}
}
}
.......
}
Now, let the browser cache the page for 60 seconds and modify the cacheservlet:
@ Webservlet (urlpatterns = {"/cacheservlet.html "})
Public class cacheservlet extends httpservlet {
@ Override
Protected void doget (httpservletrequest request, httpservletresponse response)
Throws servletexception, ioexception {
Long clientlastmodified = request. getdateheader ("If-modified-since ");
If (clientlastmodified + 60*1000> new date (). gettime () {// if it is within 60 seconds, 304 is returned directly, allowing the browser to use the local cache
Response. setstatus (304 );
Return;
}

Response. setcontenttype ("text/html; charset = gb2312 ");
Response. setdateheader ("last-modified", new date (). gettime ());
Printwriter out = response. getwriter ();
Out. Print ("Hello, cache! ");
Out. Close ();
}
}
Clear the cache, restart tomcat, and visit this page again,
Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:34:29 GMT
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:36:08 GMT
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:36:08 GMT

Hello, cache!
Refresh the page. Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:36:08 GMT
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 304 not modified
Server: APACHE-Coyote/1.1
Date: Tue, 17 Apr 2012 07:36:08 GMT
As you can see, if the server returns 304, the browser can directly use the local cache. Refresh the page one minute later:
Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:36:08 GMT
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:37:28 GMT
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:37:28 GMT

Hello, cache!
Although the client sends the IF-modified-Since Header, 200 is returned because it has exceeded 60 seconds.
2. completely eliminate the request-expires
Although the browser cache does not expire, the server can return 304, which can save bandwidth and improve the server's processing efficiency, after all, the browser sends a request to the server, can the browser directly use the local cache without asking the server when it does not expire? The answer is yes. The Expires header is used to tell the browser when the cached page expires. before expiration, the browser can directly use the local cache without asking the server.
Modify our cacheservlet:
@ Webservlet (urlpatterns = {"/cacheservlet.html "})
Public class cacheservlet extends httpservlet {
@ Override
Protected void doget (httpservletrequest request, httpservletresponse response)
Throws servletexception, ioexception {
Long clientlastmodified = request. getdateheader ("If-modified-since ");
If (clientlastmodified + 60*1000> new date (). gettime ()){
Response. setstatus (304 );
Return;
}
Response. setcontenttype ("text/html; charset = gb2312 ");
Response. setdateheader ("last-modified", new date (). gettime ());
Response. setdateheader ("expires", new date (). gettime () + 60*1000); // After 60 seconds, the browser cache expires
Printwriter out = response. getwriter ();
Out. Print ("Hello, cache! ");
Out. Close ();
}
}
Clear the cache, restart tomcat, and visit this page again,
Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:44:39 GMT
Expires: Tue, 17 Apr 2012 07:45:39 GMT
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:44:39 GMT

Hello, cache!
Browser cache:

It can be seen that the deadline for this operation is no longer none.
F5 refreshes the browser and sends a request to the server instead of directly using the local cache,
Client request:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:44:39 GMT
HOST: localhost: 8080
Connection: keep-alive
Server Response:
HTTP/1.1 304 not modified
Server: APACHE-Coyote/1.1
Date: Tue, 17 Apr 2012 07:44:40 GMT

However, if you press enter directly in the browser, the following will be displayed:

That is to say, the local cache is directly obtained, but it does not interact with the server.

So far, it seems perfect, but there are two problems: (1) browser compatibility problems, some Browsers Do not support Expires header (2) the server time may be inconsistent with the client time. If the client time lags behind the server time by one hour, it will be useless if the server's expires is set to one hour, this is indeed a problem! Fortunately, HTTP also provides another header called cache-control, which can set the cache time in seconds. This time is relative to the browser of the client.
We modify our cacheservlet again:
@ Webservlet (urlpatterns = {"/cacheservlet.html "})
Public class cacheservlet extends httpservlet {
@ Override
Protected void doget (httpservletrequest request, httpservletresponse response)
Throws servletexception, ioexception {
Long clientlastmodified = request. getdateheader ("If-modified-since ");
If (clientlastmodified + 60*1000> new date (). gettime ()){
Response. setstatus (304 );
Return;
}
Response. setcontenttype ("text/html; charset = gb2312 ");
Response. setdateheader ("last-modified", new date (). gettime ());
Response. setdateheader ("expires", new date (). gettime () + 60*1000 );
Response. setheader ("cache-control", "Max-age =" + 60); // tell the browser to cache for 60 seconds
Printwriter out = response. getwriter ();
Out. Print ("Hello, cache! ");
Out. Close ();
}
}
Clear the cache, restart tomcat, and visit this page again,
Client Requests:
GET/Cache/cacheservlet.html HTTP/1.1
Accept :*/*
Accept-language: ZH-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e; infopath.2)
Accept-encoding: gzip, deflate
If-modified-since: Tue, 17 Apr 2012 07:44:39 GMT
HOST: localhost: 8080
Connection: keep-alive server response:
HTTP/1.1 200 OK
Server: APACHE-Coyote/1.1
Last-modified: Tue, 17 Apr 2012 07:50:42 GMT
Expires: Tue, 17 Apr 2012 07:51:42 GMT
Cache-control: Max-age = 60
Content-Type: text/html; charset = gb2312
Content-Length: 12
Date: Tue, 17 Apr 2012 07:50:42 GMT

Hello, cache!
The cache-control header has been output.
Differences between several different refreshes:
(1) Ctrl + F5: Force refresh. A request is sent to the server regardless of whether the browser caches the page or not, and the IF-modified-since header is not sent.
(2) F5: If-modified-since is used for cache negotiation, but expires is invalid.
(3) Press enter in the address bar and click the page hyperlink to negotiate and the Expires header is valid.
Server Page cache:
All of the above are browser-side caches. By using templates such as velocity or freemarker, it is easy to implement server-side page caching. The general idea should be as follows:
When the Controller receives a request:
1. Check whether the responsecontent object matching the URL has been cached in memcache.
2. If not found, call the action method and store the generated responsecontent in memcache.
3. If yes, the server cache is available.
3.1 If the client cache is available (determined based on last-modified), 304 is returned directly and the client cache is used.
3.2 If the client cache is invalid, use the responsecontent cached by the server to output it to the client.
However, after cache is used, the real-time page cannot be guaranteed.
[Note]
(1) During the experiment, set the browser to automatically check the webpage.

(2) The IE browser is too stupid. It does not cache any suffix or suffix. do files (I use IE8). Therefore, during the experiment, you need to change the servlet ing path to HTML. Otherwise, the experiment may fail.

(3) Other cache-related HTTP headers include:
Pragma, etag/if-None-match
(4) Disable browser caching
Pragma: No-Cache // No Response Header for HTTP 1.0
Expires: 0
Cache-control: No-Cache
Cache-control: No-store // This setting prevents Firefox from caching

Reference: Build a high-performance web site, Guo Xin, and gain an in-depth experience in javaweb development-core Foundation, Zhang Xiaoxiang

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.