It is not easy to create a complete website through node. js. This involves reading the Page Template and extracting data from the database to build a new page and return it to the client. But this is not the case. We still need to set the header. In Chrome, if the CSS does not set the correct Content-Type, it will not work. In this case, we also need to consider the traffic volume. We need to set the cache. The cache is not just to read and read things from the memory, so it will crash the computer memory, which uses LRUAlgorithm(The minimum amount of data used recently is cleared out of the memory ). Based on cookie and database and URL rewriting, we developed a session mechanism for communication among multiple actions. For different requests to be handled by different actions, it is necessary to develop a mechanism and MVC system. I wrote these things a little later to reveal the various problems and solutions encountered in Newland. js. If we look forward to the framework directly, it is very unfavorable for us to learn languages.
This article, as the title says, is an operation cookie. The following is a complete example:
VaR HTTP = require ('http'); http. createserver (function (req, Res) {// obtain the client's cookie var cookies ={}; req. headers. cookie & req. headers. cookie. split (';'). foreach (function (cookie) {var parts = cookie. split ('='); Cookies [parts [0]. trim ()] = (parts [1] | ''). trim () ;}); console. log (cookies) // set a cookie res to the client. writehead (200, {'set-cookies': 'mycookie = test', 'content-type': 'text/plain '}); Res. end ('Hello world \ n ');}). listen (8000); console. log ('server running at http: // 127.0.0.1: 8000 /');
If you remove a few of them, it is an official example. Besides indicating that it is much simpler to return a page, it is useless at all.
VaR HTTP = require ('http'); http. createserver (function (req, Res) {res. writehead (200, {'content-type': 'text/plain '}); Res. end ('Hello world \ n ');}). listen (8000); console. log ('server running at http: // 127.0.0.1: 8000 /');
We use the HTTP. createserver callback to process all requests and responses, so everything useful is on them. The cookie is located on the headers object of the req object and is a string, which is usually converted into an object for convenience.
Writing a cookie is actually setting a key-value pair in the header. The preceding method is simple. It can actually be as follows:
Res. writehead (200, {'set-cookies': ["AAA = BBB", "CCC = DDD", "eee = fff"], 'content-type ': 'text/plain '});
However, in actual use, our cookies are not in this simple format:
Set-COOKIE: = [; =] [; expires =] [; domain =] [; Path =] [; secure] [; HTTPOnly]
HTTPOnly attributes: This is Microsoft's extension to cookies. If the "HTTPOnly" attribute is set in the cookieProgram(JS scripts, applets, etc.) will not be able to read cookie information, which can effectively prevent XSS attacks.
VaR HTTP = require ('http'); http. createserver (function (req, Res) {// obtain the client's cookie var cookies ={}; req. headers. cookie & req. headers. cookie. split (';'). foreach (function (cookie) {var parts = cookie. split ('='); Cookies [parts [0]. trim ()] = (parts [1] | ''). trim () ;}); console. log (cookies) // set a cookie res to the client. writehead (200, {'set-cookies': 'ssid = ap4gteq; expires = wed, 13-Jan-2021 22:23:01 GMT; HTTPOnly ', 'content-type ': 'text/html'}); Res. end ('Hello world \ n ');}). listen (8000); console. log ('server running at http: // 127.0.0.1: 8000 /');
Then we click the page several times and find that we can still see the SSID = ap4gteq attribute on the console, but we cannot see it on the front end (of course we can see it in firebug ).
Secure attributes: When it is set to true, it indicates that the created cookie will be transmitted to the server in a safe form, that is, it can only be passed to the server by the browser in the HTTPS connection for session verification, if it is an HTTP connection, this information is not transmitted, so the cookie content is not stolen. Same as above, we cannot find the cookie key-value pair with secure = true in document. Cookie on the client. The secure attribute prevents information leakage after being captured by the listener during the transfer process. The HTTPOnly attribute aims to prevent attacks after the program obtains the cookie. We can regard secure = true as a stricter access control than HTTPOnly.
Path attribute: Specifies the directory that can access cookies. For example, "userid = 320; Path =/shop"; indicates that the current cookie can only be used in the shop directory.
Domain attributes: Specify the host name that can access the cookie. The host name refers to different hosts in the same domain. For example, www.google.com and gmail.google.com are two different host names. By default, the cookies created on one host cannot be accessed on another host,
However, you can use the domain parameter to control it. The syntax format is: "name = value; domain = cookiedomain". Take Google as an example to achieve cross-host access, it can be written as follows:
"Name = value; domain = .google.com"; in this way, all hosts under Google.com can access this cookie.
Expires attributes: Specify the expiration time in the format of "name = value; expires = gmt_string ";
Gmt_string is a time string in GMT format. After this time, the cookie disappears and becomes inaccessible. For example, if you want to set the cookie to expire after 10 days, you can do this:
// Obtain the current time var date = new date (); var expiredays = 10; // set the date value to the date value after 10 days. settime (date. gettime () + expiredays * 24*3600*1000); // set the cookie userid and username to expire after 10 days. Res. writehead (200, {'set-cookies': "userid = 828; username = Hulk; expire =" + date. togmtstring (); 'content-type': 'text/html '});
Max-age attributes: I personally think this is more useful than expires. It was originally used to replace expires. Because you copied me from books on the market and I copied you, all of them are copying old knowledge, so expires is still in use. The value of max-age can be a positive number, indicating the time that the cookie exists from creation to expiration. In seconds, the cookie is stored on the client computer and saved as a cookie file, no matter you close your browser or your computer, it will not expire until the time has elapsed.
It can be a negative number, indicating that the cookie is only stored in the browser memory. If the browser is closed, the cookie will disappear. The default value of maxage is-1.
It can also be 0, indicating that the cookie is deleted from the client computer or browser memory.
Cookie is mainly for servers, and localstorage is for page Js. The business data required for the page can be stored in localstorage, but Authentication-related information still needs to be stored in cookies.
Cookie restrictions
I. The Browser allows the number of cookies contained in each domain name:
- Microsoft pointed out that Internet Explorer 8 has added a cookie limit of 50 for each domain name, But IE7 seems to allow 50 cookies for each domain name (update to Internet Explorer's cookie jar).
- Firefox has a maximum of 50 cookies for each domain name.
- Opera has a maximum of 30 cookies for each domain name.
- Safari/WebKit seems to have no cookie restrictions. However, if there are many cookies, the header size will exceed the server's processing limit, which may cause errors.
2. When many cookies are set, how does the browser respond. Besides Safari (you can set all cookies regardless of the number of cookies), there are two methods:
- Least recently used (least recently used (LRU) method: When the cookie has reached the limit, the oldest cookie is automatically kicked out to make some space for the latest cookie. Internet Explorer and opera use this method.
- Firefox is unique: although the last set cookie is always retained, it seems that it randomly determines which cookies are retained. There seems to be no plan (we recommend that you do not exceed the cookie limit in Firefox ).
3. Different browsers have different cookie sizes:
- Firefox and Safari allow cookies to contain up to 4097 bytes, including names, values, and equal signs.
- Opera allows cookies to contain up to 4096 bytes, including name, value, and equal sign.
- Internet Explorer allows cookies to contain up to 4095 bytes, including name, value, and equal sign.
Note: Multi-byte characters are calculated as two bytes. In all browsers, any cookie that exceeds the limit is ignored and never set.
Finally, let's see how Newland. js processes cookies.
Newland. js has an important object called httpflow, which is actually a subclass of my operational flow. It hijacks all the clearance and response. When a request comes over, the framework will process them with a new httpflow. It has a patch method to add some useful attributes and methods for the operation stream, instead of directly modifying the native object like express. js. The current practice of implementing Express. JS is a bit like prototype. js. In addition, the node. js version is not up to 1.0, so API changes are still frequent. The behavior of Express. JS is similar to that of steel wire. Moving operations to a custom object is much safer.
// For The Source horse, see the https://github.com/RubyLouvre/newland/blob/master/system/mvc.js HTTP. createserver (function (req, Res) {var flow = new flow () // creates a process object to process all asynchronous operations, such as reading view files and connecting databases to flow. patch (req, Res) services. foreach (function (FN) {fn (flow); // attach the Interceptor to the process object });//...})
In addition, HTTP Flow also hijacks res. writehead and res. setheader to enable multiple setcookie calls without overwriting each other.
// Source horse see https://github.com/RubyLouvre/newland/blob/master/system/httpflow.js Patch: function (req, Res) {This. res = res; this. req = req; this. originalurl = req. URL; this. params = {}; this. session = new store (this) This. flash = function (type, MSG ){//.....} Var flow = This; var writehead = res. writehead; var setheader = res. setheader; flow. _ setheader = setheader; Res. writehead = function () {flow. fire ('header'); writehead. apply (this, arguments); this. writehead = writehead; // restore} res. setheader = function (field, Val) {var key = field. tolowercase () if ('set-cookies' = Key) {var array = typeof val = "string "? [Val]: Val; array. foreach (function (STR) {var arr = Str. split ("="); flow. addcookie (ARR [0], arr [1])} else {If ('content-type' = Key & this. charset) {Val + = '; charset =' + this. charset;} setheader. call (this, field, Val );}}}
In addition, the operation stream has two useful methods to add or remove cookies.
// Source horse see https://github.com/RubyLouvre/newland/blob/master/system/httpflow.js addcookie: function (name, Val, OPT) {If (! This. rescookies) {This. rescookies ={}; this. rescookies [name] = [Val, opt] This. BIND ("Header", function () {var array = [] for (var I in this. rescookies) {var arr = This. rescookies [I]; array. push (cookie. stringify (I, arr [0], arr [1])} This. _ setheader. call (this. res, "set-cookie", array)} else {This. rescookies [name] = [Val, opt]} return this;}, removecookie: function (name) {var cookies = array. I Sarray (name )? Name: [name]; cookies. foreach (function (cookie) {This. addcookie (cookie, "", 0)}, this); return this ;},
EssentiallyCodeSo that we can easily add or delete cookies multiple times. I personally think that using setheader for operations (even if it has been stolen, it is still not very useful), we still use addcookie, removecookie to do it. These operations will take effect when the user calls the current res. whirehead for the first time!
Flow. addcookie ("acookie", "xxxxxxxxxx"); flow. addcookie ("bcookie", "yyyyyyy"); flow. addcookie ('rememberme ', 'yes', {expires: 0, HTTPOnly: true}) // chained method. The cookie with the same name overwrites the cookie with the latter name, the front end only generates "AAA = 2; BBB = 1" flow. addcookie ("AAA", 1 ). addcookie ("AAA", 2 ). addcookie ("BBB", 1 ). addcookie ("BBB", 1) flow. res. setheader ("Set-cookie", "user = aaa") flow. removecookie ("oldcookie") // input a string array and delete multiple cookie flows at the same time. removecookie (["mycookie", "uuer", "newcookie"])
If you want to view the cookies from the client, you can directly view the flow. Cookie. It will call a get_cookie service on the way and convert the original character form into an object.