The birth of a cookie
Because the HTTP protocol is stateless, the server-side business must be stateful. The original purpose of cookies was to store state information in the Web to facilitate server-side use. For example, to determine whether the user is the first time to visit the site. The latest specification is RFC 6265, which is a specification that is implemented jointly by the browser server.
The processing of cookies is divided into:
Servers send cookies like clients
The browser saves cookies
Each HTTP request browser then sends the cookie to the server side
Server-side sending and parsing
Send cookies
Server-side sending cookies like clients are implemented through HTTP response messages, and the Cookie,cookie format that needs to be sent as a client is set in Set-cookie as follows:
Set-cookie: "Name=value;domain=.domain.com;path=/;expires=sat, June 2016 11:29:42 GMT;" Httponly;secure "
Where Name=value is required, all others are optional. The main components of cookies are as follows:
Name: A uniquely identified cookie name. Generally speaking, the name of a cookie is case-insensitive.
Value: A string value stored in a cookie. It is best to URL-encode the name and value of a cookie
Domain:cookie is valid for which domain. This cookie information will be included in all requests sent to the domain. This value can contain subdomains, such as:
yq.aliyun.com), or it may not contain it (for example:. aliyun.com, it is valid for all subdomains of aliyun.com).
Path: Represents the path that this cookie affects, and the browser sends cookies based on this configuration, like a matching path in the specified domain.
Expires: Expiration time that indicates when the cookie should be deleted (that is, when it should stop sending this cookie to the server). If you do not set this timestamp, the browser will delete all cookies when the page closes, but you can also set the deletion time yourself. This value is GMT time format, if the client and server-side time is inconsistent, the use of expires will be biased.
Max-age: Same as expires, used to tell the browser how often this cookie expires (in seconds), not a fixed point in time. Under normal circumstances, max-age priority is higher than expires.
HttpOnly: Tell the browser not to allow the script Document.cookie to change this value, the same value is not visible in Document.cookie. However, the HTTP request sheet will still carry this cookie. Note that this value is not available in the script, but still exists as a file in the browser installation directory. This setting is usually set on the server side.
Secure: A security flag that, when specified, can be sent to the server only when using SSL links and is not delivered if it is an HTTP link. Even if the secure attribute is set, it does not mean that others cannot see the cookie information stored locally on your machine, so don't put the important information in cookies on the server-side settings
Examples of cookies are as follows:
var http = require (' http ');
var fs = require (' FS ');
Http.createserver (function (req, res) {
res.setheader (' status ', ' OK ');
Res.setheader (' Set-cookie ', ' isvisit=true;domain=.yourdomain.com;path=/;max-age=1000 ');
Res.write (' Hello World ');
Res.end ();
}). Listen (8888);
Console.log (' Running localhost:8888 ')
Setting the Set-cookie directly is too primitive, we can do the following encapsulation of the cookie Setup process:
var serilize = function (name, Val, options) {if (!name) {throw new Error ("Coolie m
UST have name ");
var enc = encodeuricomponent;
var parts = []; val = (val!== null && val!== undefined)?
Val.tostring (): ""; options = Options | |
{};
Parts.push (ENC (name) + "=" + Enc (val));
Domain must contain two dots if (options.domain) {Parts.push ("domain=" + options.domain);
} if (Options.path) {Parts.push ("path=" + Options.path); //If the expires and Max-age browsers are not set to empty cookies if (options.expires) {Parts.push ("expires=" + options.expires.toGMTSt) when the page closes
Ring ());
} if (Options.maxage && typeof options.maxage = = "Number") {Parts.push ("max-age=" + options.maxage);
} if (options.httponly) {Parts.push ("HttpOnly");
} if (options.secure) {Parts.push ("secure");
return Parts.join (";"); }
It is important to note that if you set a past time for the cookie, the browser deletes the cookie immediately, and the domain entry must have two points, so it cannot be set to localhost:
Something that wasn ' t made clear to me here and totally confused me for a while is that domain names must contain at LEAs T two dots (.), hence ' localhost ' is invalid and the browser'll refuse to set the cookie!
Server-side parsing cookies
Cookies can be set to different domains and paths, so for the same name value, they can be duplicated under different paths in different domains, and the browser will be prioritized in the order of the best match to the current request URL or page address
So when the front end passes to the server side the cookie has multiple duplicate name value, we only need the one that matches the most, that is, the first one. The server-side parsing code is as follows:
var parse = function (CStr) {
if (!cstr) {return
null;
}
var dec = decodeuricomponent;
var cookies = {};
var parts = cstr.split (/\s*;\s*/g);
Parts.foreach (function (p) {
var pos = p.indexof (' = ');
Before name and value are stored in a cookie, it must be encoded with the
var name = pos >-1 Dec (p.substr (0, POS)): P;
var val = pos >-1? Dec (P.SUBSTR (pos + 1)): null;
Just get the best match for the
if (!cookies.hasownproperty (name)) {
Cookies[name] = val;
} /* Else if (!cookies[name] instanceof Array) {
Cookies[name] = [Cookies[name]].push (val);
} else {
Cookies[name].push (val);
} */
});
return cookies;
Access to the client
The browser manages cookies that are passed in the background and allows developers to use Document.cookie in JavaScript to access cookies. But this interface is very lame to use. It will behave differently because of the way it is used.
When used to get the property value, Document.cookie returns all the strings available for the current page (based on the cookie's domain, path, expiration time, and security settings), and the format of the string is as follows:
"Name1=value1;name2=value2;name3=value3";
When used to set a value, the Document.cookie property can be set to a new cookie string. This string is interpreted and added to the existing cookie collection. Such as:
Document.cookie = "_fa=aaaffffasdsf;domain=.dojotoolkit.org;path=/"
Setting Document.cookie does not overwrite cookies unless the Set name value domain path is duplicated with an existing cookie.
Because cookies are very inconvenient to read and write, we can encapsulate some functions to handle cookies, mainly for the addition, modification, deletion of cookies.
var cookieutils = {get:function (name) {var cookiename=encodeuricomponent (name) + "=";
Only get the most matching name,value var Cookiestart = document.cookie.indexOf (cookiename);
var cookievalue = null;
if (Cookiestart >-1) {//from Cookiestart the var cookieend = document.cookie.indexOf ('; ', Cookiestart); From = back start if (Cookieend > 1) {cookievalue = decodeURIComponent (document.cookie.substring Cookiestart + C
Ookiename.length, Cookieend)); else {cookievalue = decodeURIComponent (document.cookie.substring (Cookiestart + cookiename.length, Document.cooki
E.length));
} return cookievalue;
}, Set:function (name, Val, options) {if (!name) {throw new Error ("Coolie must have name");
var enc = encodeuricomponent;
var parts = []; val = (val!== null && val!== undefined)?
Val.tostring (): ""; options = Options | |
{}; Parts.pUsh (ENC (name) + "=" + Enc (val));
Domain must contain two dots if (options.domain) {Parts.push ("domain=" + options.domain);
} if (Options.path) {Parts.push ("path=" + Options.path); //If the expires and Max-age browsers are not set to empty cookies if (options.expires) {Parts.push ("expires=" + options.exp) when the page closes
Ires.togmtstring ()); } if (Options.maxage && typeof options.maxage = = "Number") {Parts.push ("max-age=" + options.maxage
);
} if (options.httponly) {Parts.push ("HttpOnly");
} if (options.secure) {Parts.push ("secure");
} Document.cookie = Parts.join (";");
Delete:function (name, options) {options.expires = new date (0);//set to past date This.set (name, null, options);
}
}
Caching benefits
Generally speaking, Web caching refers to HTTP devices that can automatically save copies of common HTTP requests. For front-end developers, browsers play an important role. In addition to the common there are a variety of proxy servers can also do caching. When a Web request arrives at the cache, the cache extracts the contents of the replica from the local copy without having to go through the server. This brings the following benefits:
Cache reduces redundant data transfer and saves traffic
Caching alleviates the bandwidth bottleneck problem. Pages can be loaded faster without the need for more bandwidth
Caching eases the momentary congestion and reduces the demand for the original server.
Caching reduces the distance delay because it is slower to load a page from a remote location.
Cache type
Caching can be private to a single user, or it can be shared by multiple users. Private caching is called a private cache, and shared caching is called a public cache.
Private cache
Private caching is only for proprietary users, so there is no need for a lot of space and cheap. There is a built-in private cache in a Web browser--most browsers cache common resources in the disk and memory of your PC. For example, the cache location of the Chrome browser is located in: C:\Users\Your_Account\AppData\Local\Google\Chrome\User Data\default in the cache folder and media cache folder.
Public cache
The public cache is a special shared proxy server, known as a caching proxy or proxy cache (a use of a reverse proxy). The public cache accepts access from multiple users, so it is better to reduce redundant traffic.
Each client in the following illustration will repeatedly access a resource to the server (not in the private cache), so it accesses the server multiple times, increasing server pressure. When using shared public caching, caching only needs to be taken from the server once, and then the server can be reduced significantly to reduce server pressure.
In fact, in practical applications, a hierarchical public cache is usually used, the basic idea is to use small cheap cache near the client, and at a higher level, a larger, more powerful cache is used to load resources shared by multiple users.
Cache processing Process
For the front-end developers, we deal primarily with caching in the browser, so the above diagram process is simplified to:
The following diagram shows a Web site, the request results of different resources, which can see some resources directly from the cache read, and some resources and the server to verify, and some resources from the server side to get.
Note that all the questions we discuss about caching resources are only for GET requests. For post, DELETE, put, this kind of behavioral operation usually does not do any caching
Value of freshness limit
HTTP retains a copy of the server resource over a period of time, known as a freshness limit, through caching. This requires that the same resources are not passed through the server for a period of time. In the HTTP protocol, Cache-control and expires can be used to set the threshold for freshness, which is the new response header in HTTP1.1, and the response head in HTTP1.0. The two do the same thing, but because Cache-control use relative time, and expires may have the client and server-side time is not the same problem, so we are more inclined to choose Cache-control.
Cache-control
Now let's look at what property values Cache-control can set:
Max-age (s) specifies the maximum effective time to set the cache, defined as the length of time. When the browser sends a request to the server, the browser will no longer send requests to the server during the Max-age period.
When the page is accessed for the second time in 5 seconds, the browser obtains the resource directly from the cache
public specifies that the response can be cached in the proxy cache and can be shared by multiple users. If private is not explicitly specified, the default is public.
Private responses can only be cached in the private cache and cannot be placed on the proxy cache. Resources that are sensitive to some user information are usually set to private.
No-cache indicates that the resource must be verified with the server (depending on if-none-match and etag) before deciding whether to use the local cache.
If the previous deal on Cache.png is changed to the following, then every time the page is accessed, the browser needs to go to the server side to verify that the resource has not been changed.
Fs.readfile ('./cache.png ', function (err, file) {
console.log (req.headers);
Console.log (Req.url)
if (!req.headers[' If-none-match ')) {
res.setheader (' Cache-control ', "No-cache, Max-age= "+ 5);
Res.setheader (' Content-type ', ' images/png ');
Res.setheader (' Etag ', "ffff");
Res.writehead (' n ', ' not Modified ');
Res.end (file);
else {
if (req.headers[' if-none-match '] = = = ' FFFF ') {
res.writehead (' 304 ', ' not Modified ');
Res.end ();
} else {
res.setheader (' Cache-control ', "max-age=" + 5);
Res.setheader (' Content-type ', ' images/png ');
Res.setheader (' Etag ', "ffff");
Res.writehead (' n ', ' not Modified ');
Res.end (file);}}
);
No-store absolutely prohibits caching of any resources, that is, each time a user requests a resource, a request is sent to the server, and the complete resource is downloaded each time. Typically used for confidential resources.
For the use of Cache-control, see this picture below (from large)
Freshness limit for clients
Cache-control can be set not only in the response header, but also in the request header. The browser sets Cache-control through the request header to determine whether to read resources from the cache. That's why sometimes you click on the Browser Refresh button and return in the address bar to see completely different results in the network module
Expires
Using expires is not recommended, it specifies a specific expiration date instead of a number of seconds. Because many servers and clients have clock inconsistencies, it is best to use Cache-control.
Server re-verification
The cached resource in the browser or proxy cache expires, and does not mean that it has a real difference to the resources on the original server, only that it is time to check. This situation is known as server re-validation.
If the resource changes, a new resource needs to be taken and the old resource is replaced in the cache.
If the resource does not change, the cache only needs to get a new response header, and a new expiration time to update the resource expiration time in the cache.
HTTP1.1 is recommended for use in If-none-match/etag, and if-modified-since/last-modified in HTTP1.0.
ETag and If-none-match
Generates a hash string based on the entity content that identifies the state of the resource and is generated by the server. The browser passes this string back to the server to verify that the resource has been modified, and if not, the procedure is as follows (the picture comes from a brief discussion of the Web cache):
In the demo above we've seen how the server side validates ETag:
Because the ETag has the server constructs, must guarantee the ETag uniqueness in the cluster environment
If-modified-since and Last-modified
These are the request/response headers used in HTTP1.0 to verify that the resource is out of date, the two headers are dates, and the validation process is similar to ETag, which is not described in detail here. When you use these two headers to verify that a resource is updated, the following problems exist:
Some document resources are periodically rewritten, but the actual content does not change. The file metadata now shows that the file's most recent modification date is not the same as if-modified-since, resulting in unnecessary responses.
Some document resources have been modified, but it is not important to modify the content, do not need all the cache update (such as code comments)
About the cache update problem, please see here Zhang Yunlong answer, this article does not expand in detail.
This demo code is as follows:
OK, this article on the introduction of cookies to the end, I hope you can enjoy.