附录:常用HTTP响应头和请求头信息对照表
Node简介
第一个node程序
module(模块系统)
npm包管理器
模块系统优先级
认识http内置模块
url内置模块
path内置模块
fs内置模块
http模块服务端进阶
http报文浅析
url模块进阶
path模块进阶
querystring模块进阶
了解Buffer和Stream
os模块
Buffer模块
Stream模块
http模块客户端
Cookie浅析
什么是 Cookie
Cookie 是什么,有以下几个点:
- Cookie 就是浏览器储存在用户电脑上的一小段文本文件
- Cookie 是纯文本格式,不包含任何可执行的代码
- Cookie 由键值对构成,由分号和空格隔开
- Cookie 虽然是存储在浏览器,但是通常由服务器端进行设置
- Cookie 的大小限制在 4kb 左右
Cookie 是怎样工作的
Cookie 是如何工作的:
1. 首先,我们假设当前域名下还是没有 Cookie 的
2. 接下来,浏览器发送了一个请求给服务器(这个请求是还没带上 Cookie 的)
3. 服务器设置 Cookie 并发送给浏览器(当然也可以不设置)
4. 浏览器将 Cookie 保存下来
5. 接下来,以后的每一次请求,都会带上这些 Cookie,发送给服务器
Cookie 的属性选项
每个 Cookie 都有一定的属性,如什么时候失效,要发送到哪个域名,哪个路径等等。在设置任一个 Cookie 时都可以设置相关的这些属性,当然也可以不设置,这时会使用这些属性的默认值。
expires / max-age
expires / max-age
都是控制 Cookie 失效时刻
的选项。如果没有设置这两个选项,则默认有效期为 session,即会话 Cookie。这种 Cookie 在浏览器关闭后就没有了。
expires
expires
选项用来设置 Cookie 什么时间内有效,expires
其实是 Cookie 失效日期。expires
必须是 GMT 格式的时间(可以通过 new Date().toGMTString()
或者 new Date().toUTCString()
来获得)
const http = require("http");
let server = http.createServer(function(req,res){
if(req.url === "/"){
let cookie0 = "testName0=testValue0;expires=" + (new Date(Date.now() + 10000).toGMTString());
let cookie1 = "testName1=testValue1";
res.setHeader("Set-Cookie",[cookie0,cookie1]);
res.end();
}
});
server.listen(8080);
上面的代码服务器设置了两个 Cookie,一个设置了失效时刻,另外一个没有设置,也就是默认的失效时刻 session。现在我们重启服务并且刷新一下页面。
现在响应头部已经加上了响应的设置失效时刻的字段了。在控制台输入下面的代码。
console.log(`现在的 cookie 是:${document.cookie}`)
setTimeout(() => {
console.log(`5 秒后的 cookie 是:${document.cookie}`)
}, 5000)
setTimeout(() => {
console.log(`10 秒后的 cookie 是:${document.cookie}`)
}, 10000)
所以,Cookie 的失效时刻到了之后,通过 document.cookie 就访问不到这个 Cookie 了,当然以后发送请求也不会再带上这个失效的 Cookie 了。
max-age
expires
是 http/1.0 协议中的选项,在新的 http/1.1 协议中 expires
已经由 max-age
选项代替,两者的作用都是限制 Cookie 的有效时间。expires
的值是一个时间点 (Cookie 失效时刻 = expires
),而 max-age
的值是一个以秒
为单位时间段 (Cookie 失效时刻 = 创建时刻 + max-age
)
const http = require("http");
let server = http.createServer(function(req,res){
if(req.url === "/"){
let cookie0 = "testName0=testValue0;max-age=1000";
let cookie1 = "testName1=testValue1";
res.setHeader("Set-Cookie",[cookie0,cookie1]);
res.end();
}
});
server.listen(8080);
优先级
如果同时设置了 max-age 和 expires,以 max-age 的时间为准。
const http = require("http");
let server = http.createServer(function(req,res){
if(req.url === "/"){
let cookie0 = "testName0=testValue0;
let cookie1 = "testName1=testValue1;expires=" + (new Date(Date.now() + 30000).toGMTString()) + "; max-age=60000";
let cookie2 = "testName2=testValue2; max-age=60000;
res.setHeader("Set-Cookie",[cookie0,cookie1,cookie2]);
res.end();
}
});
server.listen(8080);
domain 和 path
name
、domain
和 path
可以标识一个唯一的 Cookie。domain
和 path
两个选项共同决定了 Cookie 何时被浏览器自动添加到请求头部中发送出去。
如果没有设置这两个选项,则会使用默认值。domain
的默认值为设置该 Cookie 的网页所在的域名,path
默认值为设置该 Cookie 的网页所在的目录。
httpOnly
这个选项用来设置 Cookie 是否能通过 js 去访问。默认情况下,Cookie 不会带 httpOnly
选项(即为空),客户端是可以通过 js 代码去访问(包括读取、修改、删除等)这个 Cookie 的。当 Cookie 带 httpOnly
选项时,客户端则无法通过 js 代码去访问(包括读取、修改、删除等)这个 Cookie。
看看代码吧,修改 main.js,保存重启服务,刷新页面。
const http = require("http");
let server = http.createServer(function(req,res){
if(req.url === "/"){
let cookie0 = "notHttpOnly=testValue";
let cookie1 = "httpOnlyTest=testValue;httpOnly=true";
res.setHeader("Set-Cookie",[cookie0,cookie1]);
res.end();
}
});
server.listen(8080);
看图,设置了 httpOnly
的 Cookie 多了一个勾。而且通过 document.cookie
无法访问到那个 Cookie。
在客户端是不能通过 js 代码去设置 一个 httpOnly
类型的 Cookie 的,这种类型的 Cookie 只能通过服务端来设置,发送请求的时候,我们看到请求头还是会带上这个设置了 httpOnly
的 Cookie.
设置 Cookie
明确一点:Cookie 可以由服务端设置,也可以由客户端设置。看到这里相信大家都可以理解了吧。
服务端设置 Cookie
看回刚刚的那张图,我们设置了很多个 Cookie。
- 一个 Set-Cookie 字段只能设置一个 Cookie,当你要想设置多个 Cookie,需要添加同样多的 Set-Cookie 字段
- 服务端可以设置 Cookie 的所有选项:expires、domain、path、secure、HttpOnly
客户端设置 Cookie
在网页即客户端中我们也可以通过 js 代码来设置 Cookie。
设置
document.cookie = 'name=value'
可以设置 Cookie 的下列选项:expires、domain、path,各个键值对之间都要用 ;
和 空格
隔开
document.cookie='name=value; expires=Thu, 26 Feb 2116 11:50:25 GMT; domain=sankuai.com; path=/';
secure
只有在 https 协议的网页中,客户端设置 secure 类型的 Cookie 才能成功
HttpOnly
客户端中无法设置 HttpOnly 选项
删除 Cookie
Cookie 的 name、path 和 domain 是唯一标识一个 Cookie 的。我们只要将一个 Cookie 的 max-age 设置为 0,就可以删除一个 Cookie 了。
let removeCookie = (name, path, domain) => {
document.cookie = `${name}=; path=${path}; domain=${domain}; max-age=0`
}
Cookie 的作用域和作用路径
作用域
在说这个作用域之前,我们先来对域名做一个简单的了解。
子域,是相对父域来说的,指域名中的每一个段。各子域之间用小数点分隔开。放在域名最后的子域称为最高级子域,或称为一级域,在它前面的子域称为二级域。
news.163.com
和 sports.163.com
是子域,163.com
是父域。
当 Cookie 的 domain 为 news.163.com
,那么访问 news.163.com
的时候就会带上 Cookie;
当 Cookie 的 domain 为 163.com
,那么访问 news.163.com
和 sports.163.com
就会带上 Cookie
作用路径
当 Cookie 的 domain 是相同的情况下,也有是否带上 Cookie 也有一定的规则。
在子路径内可以访问访问到父路径的 Cookie,反过来就不行。
看看例子,还是先修改 main.js
const http = require("http");
let server = http.createServer(function(req,res){
if(req.url === "/parent"){
let cookie = "parent-name=parent-value;path=/parent";
res.setHeader("Set-Cookie",cookie);
res.end();
}else if(req.url === "/parent/childA"){
let cookie = "child-name-A=child-value-A;path=/parent/childA";
res.setHeader("Set-Cookie",cookie);
res.end();
}else if(req.url === "/parent/childB"){
let cookie = "child-name-B=child-value-B;path=/parent/childB";
res.setHeader("Set-Cookie",cookie);
res.end();
}else{
res.end("Error!");
}
});
server.listen(3000);
下面这里的 “域” 应该改为路径