当你在浏览器地址栏中输入eloquentjavascript.net/17_http.html时,浏览器会首先找到和eloquentjavascript.net相关联的服务器的地址,然后尝试通过80端口建立TCP连接,其中80端口是HTTP的默认通信端口。
先建立TCP链接(三次握手)再发送HTTP请求
如果该服务器存在并且接受了该连接,浏览器就会发送如下内容。
GET 17_http.html HTTP/1.1
Host:eloquentjavascript.net
User-Agent:Your browser's name
由客户端发出的信息叫做请求。请求中的第一个单词是请求方法。GET表示我们希望得到一个我们指定的资源。DELETE——删除一个资源,PUT——替换资源,POST——发送消息。服务器可以拒绝请求。
方法名后的请求部分是所请求的资源的路径。
请求的第一行中位于资源路径后面的HTTP/1.1用来表明所使用的HTTP协议的版本。
然后服务器会通过同一个链接返回如下内容。
HTTP/1.1 200 OK
Content-Length:65585
Content-Type:text/html
Last-Modified:Web,09 Apr 2014 10:48:09 GMT
<!DOCTYPE html>
...the rest of the document
服务器的响应也是以版本号开始的。版本号后面是应答状态,首先是一个三位的状态码,然后是一个可读的字符串。
2——请求成功 4——请求有错误 5——服务器端有问题,请求没错
401需要输入用户名和密码
报文三个部分组成:起始行、首部、主体(不是必须)
浏览器端的JavaScript发送HTTP请求所用的接口叫做XMLHttpRequest。(和XML没什么卵关系)
var req = new XMLHttpRequest();
req.open("GET","F:/scripts/fruit.xml",false);
req.send(null);
send方法发送请求,open的第三个参数设置为true,浏览器会进行异步请求。如果为false,send会在接收到请求的响应后才返回结果。
GET和POST
GET请求会把表单数据追加到URL的最后;
POST请求会把表单数据包括在请求的体中。
w3school:
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
然而,在以下情况中,请使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
Head First Servlets and JSP
1.GET中的总字符数是有限的(取决于服务器);
2.用GET发送的数据会追加到URL的后面,在浏览器地址栏中显示出来,所以你发送的数据会完全暴露。最好不要把口令或其他敏感数据作为GET请求的一部分发送!
3.由于前面的第2点,如果你使用POST而不是GET,用户就不能对一个表单提交建立书签。
XML和JSON都是用来存储信息的。
HEAD方法与GET方法类似,但服务器在响应中只返回首部,不会返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查。
TRACE方法允许客户端在最终将请求发送给服务器时,看看它变成了什么样子。TRACE方法主要用于诊断。
OPTIONS方法请求Web服务器告知其支持的各种功能。
了不起的node.js
HTTP属于TCP上层的协议。
HTTP协议构建在请求和响应的概念上,对应在Node.js中就是由http.ServerRequest和http.ServerResponse这两个构造器构造出来的对象。
当用户浏览一个网站时,用户代理(浏览器)会创建一个请求,该请求通过TCP发送给Web服务器,随后服务器会给出响应。
Web服务器:
require('http').createServer(function(req,res){...})
当客户端连入时会执行一个回调函数。req请求(req.header,req.url,req.method),res响应(res.writeHead(),res.end())
req.on(‘data’,function(...){...})//有数据传入
req.on(‘end’,function(...){...})
输出表单
<form method="POST" action="/url">...</form>
method GET/POST | 规定用于发送 form-data 的 HTTP 方法。
POST 方法浏览器就会按分段传输的方法将数据发送给服务器。
GET 方法浏览器会将数据直接附在表单的 action URL 之后。这两者之间用问号进行分隔。
action向何处发送表单数据。
《图解HTTP》
负责传输的IP协议,网络层
确保可靠性的TCP协议,传输层,将大块数据分割成以报文段为单位的数据包进行管理,三次握手
负责域名解析的DNS服务(Domain Name System)应用层

使用Cookie的状态管理
Cookie会根据从服务器端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie,cookie中包含了一个由名字=值(name=value)这样的信息构成的任意列表。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去。
Set-Cookie: name=value[; expires=date][; path=path][; domain=domain][; secure]
Cookie: name1=value1[; name2 =value2]...
通信数据转发程序:代理,网关,隧道
保存资源的缓存
Session
通过Cookie,浏览器和服务器可以实现状态的记录。但是Cookie并非是完美的,前文提及的体积过大就是一个显著的问题,最为严重的问题是Cookie可以在前后端进行修改,因此数据就极容易被篡改和伪造。如果服务器端有部分逻辑是根据Cookie中的isVIP字段进行判断,那么一个普通用户通过修改Cookie就可以轻松享受到VIP服务了。综上所述,Cookie对于敏感数据的保护是无效的。
为了解决Cookie敏感数据的问题,Session应运而生。服务器可以为每个用户浏览器创建一个会话对象(session对象)。Session的数据只保留在服务器端,客户端无法修改,这样数据的安全性得到一定的保障,数据也无须在协议中每次都被传递。
如何将每个客户和服务器中的数据一一对应起来。
一、基于Cookie来实现用户和数据的映射;
一旦服务器检查到用户请求Cookie中没有携带该值sessionid,它就会为之生成一个值,这个值是唯一且不重复的值,并设定超时时间。
二、通过查询字符串来实现浏览器端和服务器端数据的对应。
检查请求的查询字符串,如果没有值,会先生成新的带值的URL。然后形成跳转,让客户端重新发起请求。
cookie与session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
HTTP缺点
被窃听,被伪装,被篡改,总的来说就是不安全。
HTTP+加密+认证+完整性保护=HTTPS
共享密钥加密(对称密钥加密)
一对相同的钥匙,一个保存在客户端,一个保存在服务器
公开密钥加密
发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。(公开密钥只能上锁不能解锁,只有私钥可以解锁,两把钥匙都属于接收方——服务器)RSA算法
验证公开密钥是真东西——公钥证书
数字签名——说明是谁编写的报文,同时证明报文未被篡改过。
服务器将变长报文提取为定长的摘要,并对摘要应用了一个“签名”函数,这个函数会将用户的私有密钥作为参数。一旦计算出签名,服务器就将其附加在报文的末尾,并将报文和签名都发送给客户端。
私钥加密,公钥解密这种场景用作签名的, 就是校验信息发送者身份. 只有通过特定私钥的的信息才能被公开出来的公钥解密. 这就唯一确定了信息发送者, 达到签名(不可抵赖)的目的。
公钥证书=服务器的公开钥匙+数字证书认证机构的数字签名

在发送已加密的HTTP报文之前,客户端和服务器要进行一次SSL握手。客户端验证服务器证书,提取公钥,用这公钥加密主密钥然后发送给服务器。服务器用私钥解密出主密钥。服务器和客户端使用主密钥进行对称加密解密数据。
用SSL在传输中加密应用数据,然后将加密的数据在传输中传给TCP。
网络攻击
XSS(跨站脚本攻击)运行非法的HTML标签或者JavaScript脚本
SQL注入 运行非法SQL语句
HTTP优化
持久连接
HTTP/1.0客户端发送一个Connection:Keep-Alive请求首部来激活keep-alive连接
如果服务器支持keep-alive,就回送一个Connection:Keep-Alive首部,否则就不回送。
HTTP/1.1持久连接在默认情况下是激活的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显式地添加一个Connection:close首部。
Content-Length要正确或者是用分块传输编码方式编码的。
管道化连接
在响应到达之前,可以将多条请求放入队列。
客户端不应该以管道化方式传送POST请求。
缓存
服务器用HTTP/1.0+的Expires首部或HTTP/1.1的Cache-Control:max-age响应首部来指定过期日期,同时还会带有响应主体。
Cache-Control:max-age:max-age值定义了文档的最大使用期——从第一次生成文档到文档不再新鲜、无法使用为止,最大的合法生存时间(以秒为单位)
Cache-Control: max-age=484200 相对时间
Expires:指定一个绝对的过期日期,如果过期日期已经过了,就说明不再新鲜了。
Expires: Fri,05,Jul,2002,05:00:00 GMT 绝对时间
再验证
HTTP允许缓存向原始服务器发送一个“条件GET”,只有条件为真时,Web服务器才会返回对象。
If-Modified-Since:
如果自指定日期后,文档被修改了,If-Modified-Since条件就为真,通常GET就会成功执行。携带新首部的新文档会被返回给缓存,新首部除了其他信息之外,还包含了一个新的过期日期。
如果自指定日期后,文档没被修改过,条件就为假,会向客户端返回一个小的304Not Modified响应报文,不会返回文档的主体,一般会发送一个新的过期日期。
If-None-Match:
如果tags与Etag不匹配,请求新对象,否则返回304。
控制缓存的能力
Cache-Control: no-store/no-cache
no-stroe禁止缓存对响应进行复制。no-cache可以存储在本地缓存器中,只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
在HTML控制缓存
<meta http-equiv="Cache-control" content="no-cache">
媒体类型
Content-Type首部字段说明了实体主体的MIME类型。MIME类型由一个主媒体类型(text、image或audio等)后面跟一条斜线以及一个子类型组成。
MIME中的multipart(多部分)电子邮件报文中包含多个报文,它们合在一起作为单一的复杂报文发送。每一部分都是独立的,有各自的描述其内容的集;不同的部分之间用分界字符串连接在一起。
内容编码
Context-Encoding首部说明编码使用的算法。
Accept-Encoding首部客户端支持的编码方式。
传输编码
内容编码是对实体部分编码,而传输编码则作用在整个报文
Transfer-Encoding 告知接收方进行了何种编码
TE 告知服务器可以使用何种编码
字符
Content-Type首部中使用charset参数 或者
在HTML<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-2022-jp">
重定向
HTTP重定向
客户端发送一条请求
服务器没有回送带有HTTP状态码200的Web页面主体,而是回送了一个带有状态码302的重定向报文,附有Location: 新的IP地址
客户端会用重定向URL重新发送请求,这次会发送给新的IP地址的主机
NAT
Network Address Translation 网络地址转换
交换机或其他第四层设备会检测输入分组中的TCP/IP地址,并通过修改目的IP地址,对分组进行相应的转发。
当你在浏览器地址栏中输入eloquentjavascript.net/17_http.html时,浏览器会首先找到和eloquentjavascript.net相关联的服务器的地址,然后尝试通过80端口建立TCP连接,其中80端口是HTTP的默认通信端口。
先建立TCP链接(三次握手)再发送HTTP请求
如果该服务器存在并且接受了该连接,浏览器就会发送如下内容。
由客户端发出的信息叫做请求。请求中的第一个单词是请求方法。GET表示我们希望得到一个我们指定的资源。DELETE——删除一个资源,PUT——替换资源,POST——发送消息。服务器可以拒绝请求。
方法名后的请求部分是所请求的资源的路径。
请求的第一行中位于资源路径后面的HTTP/1.1用来表明所使用的HTTP协议的版本。
然后服务器会通过同一个链接返回如下内容。
服务器的响应也是以版本号开始的。版本号后面是应答状态,首先是一个三位的状态码,然后是一个可读的字符串。
2——请求成功 4——请求有错误 5——服务器端有问题,请求没错
401需要输入用户名和密码
报文三个部分组成:起始行、首部、主体(不是必须)
浏览器端的JavaScript发送HTTP请求所用的接口叫做XMLHttpRequest。(和XML没什么卵关系)
send方法发送请求,open的第三个参数设置为true,浏览器会进行异步请求。如果为false,send会在接收到请求的响应后才返回结果。
GET和POST
GET请求会把表单数据追加到URL的最后;
POST请求会把表单数据包括在请求的体中。
w3school:
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
然而,在以下情况中,请使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
Head First Servlets and JSP
1.GET中的总字符数是有限的(取决于服务器);
2.用GET发送的数据会追加到URL的后面,在浏览器地址栏中显示出来,所以你发送的数据会完全暴露。最好不要把口令或其他敏感数据作为GET请求的一部分发送!
3.由于前面的第2点,如果你使用POST而不是GET,用户就不能对一个表单提交建立书签。
XML和JSON都是用来存储信息的。
HEAD方法与GET方法类似,但服务器在响应中只返回首部,不会返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查。
TRACE方法允许客户端在最终将请求发送给服务器时,看看它变成了什么样子。TRACE方法主要用于诊断。
OPTIONS方法请求Web服务器告知其支持的各种功能。
了不起的node.js
HTTP属于TCP上层的协议。
HTTP协议构建在请求和响应的概念上,对应在Node.js中就是由http.ServerRequest和http.ServerResponse这两个构造器构造出来的对象。
当用户浏览一个网站时,用户代理(浏览器)会创建一个请求,该请求通过TCP发送给Web服务器,随后服务器会给出响应。
Web服务器:
require('http').createServer(function(req,res){...})当客户端连入时会执行一个回调函数。req请求(req.header,req.url,req.method),res响应(res.writeHead(),res.end())
输出表单
<form method="POST" action="/url">...</form>method GET/POST | 规定用于发送 form-data 的 HTTP 方法。
POST 方法浏览器就会按分段传输的方法将数据发送给服务器。
GET 方法浏览器会将数据直接附在表单的 action URL 之后。这两者之间用问号进行分隔。
action向何处发送表单数据。
《图解HTTP》

负责传输的IP协议,网络层
确保可靠性的TCP协议,传输层,将大块数据分割成以报文段为单位的数据包进行管理,三次握手
负责域名解析的DNS服务(Domain Name System)应用层
使用Cookie的状态管理
Cookie会根据从服务器端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie,cookie中包含了一个由名字=值(name=value)这样的信息构成的任意列表。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去。
通信数据转发程序:代理,网关,隧道
保存资源的缓存
Session
通过Cookie,浏览器和服务器可以实现状态的记录。但是Cookie并非是完美的,前文提及的体积过大就是一个显著的问题,最为严重的问题是Cookie可以在前后端进行修改,因此数据就极容易被篡改和伪造。如果服务器端有部分逻辑是根据Cookie中的isVIP字段进行判断,那么一个普通用户通过修改Cookie就可以轻松享受到VIP服务了。综上所述,Cookie对于敏感数据的保护是无效的。
为了解决Cookie敏感数据的问题,Session应运而生。服务器可以为每个用户浏览器创建一个会话对象(session对象)。Session的数据只保留在服务器端,客户端无法修改,这样数据的安全性得到一定的保障,数据也无须在协议中每次都被传递。
如何将每个客户和服务器中的数据一一对应起来。
一、基于Cookie来实现用户和数据的映射;
一旦服务器检查到用户请求Cookie中没有携带该值sessionid,它就会为之生成一个值,这个值是唯一且不重复的值,并设定超时时间。
二、通过查询字符串来实现浏览器端和服务器端数据的对应。
检查请求的查询字符串,如果没有值,会先生成新的带值的URL。然后形成跳转,让客户端重新发起请求。
cookie与session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
HTTP缺点
被窃听,被伪装,被篡改,总的来说就是不安全。

HTTP+加密+认证+完整性保护=HTTPS
共享密钥加密(对称密钥加密)
一对相同的钥匙,一个保存在客户端,一个保存在服务器
公开密钥加密
发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。(公开密钥只能上锁不能解锁,只有私钥可以解锁,两把钥匙都属于接收方——服务器)RSA算法
验证公开密钥是真东西——公钥证书
数字签名——说明是谁编写的报文,同时证明报文未被篡改过。
服务器将变长报文提取为定长的摘要,并对摘要应用了一个“签名”函数,这个函数会将用户的私有密钥作为参数。一旦计算出签名,服务器就将其附加在报文的末尾,并将报文和签名都发送给客户端。
私钥加密,公钥解密这种场景用作签名的, 就是校验信息发送者身份. 只有通过特定私钥的的信息才能被公开出来的公钥解密. 这就唯一确定了信息发送者, 达到签名(不可抵赖)的目的。
公钥证书=服务器的公开钥匙+数字证书认证机构的数字签名
在发送已加密的HTTP报文之前,客户端和服务器要进行一次SSL握手。客户端验证服务器证书,提取公钥,用这公钥加密主密钥然后发送给服务器。服务器用私钥解密出主密钥。服务器和客户端使用主密钥进行对称加密解密数据。
用SSL在传输中加密应用数据,然后将加密的数据在传输中传给TCP。
网络攻击
XSS(跨站脚本攻击)运行非法的HTML标签或者JavaScript脚本
SQL注入 运行非法SQL语句
HTTP优化
持久连接
HTTP/1.0客户端发送一个Connection:Keep-Alive请求首部来激活keep-alive连接
如果服务器支持keep-alive,就回送一个Connection:Keep-Alive首部,否则就不回送。
HTTP/1.1持久连接在默认情况下是激活的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显式地添加一个Connection:close首部。
Content-Length要正确或者是用分块传输编码方式编码的。
管道化连接
在响应到达之前,可以将多条请求放入队列。
客户端不应该以管道化方式传送POST请求。
缓存
服务器用HTTP/1.0+的Expires首部或HTTP/1.1的Cache-Control:max-age响应首部来指定过期日期,同时还会带有响应主体。
Cache-Control:max-age:max-age值定义了文档的最大使用期——从第一次生成文档到文档不再新鲜、无法使用为止,最大的合法生存时间(以秒为单位)
Cache-Control: max-age=484200 相对时间
Expires:指定一个绝对的过期日期,如果过期日期已经过了,就说明不再新鲜了。
Expires: Fri,05,Jul,2002,05:00:00 GMT 绝对时间
再验证
HTTP允许缓存向原始服务器发送一个“条件GET”,只有条件为真时,Web服务器才会返回对象。
If-Modified-Since:
如果自指定日期后,文档被修改了,If-Modified-Since条件就为真,通常GET就会成功执行。携带新首部的新文档会被返回给缓存,新首部除了其他信息之外,还包含了一个新的过期日期。
如果自指定日期后,文档没被修改过,条件就为假,会向客户端返回一个小的304Not Modified响应报文,不会返回文档的主体,一般会发送一个新的过期日期。
If-None-Match:
如果tags与Etag不匹配,请求新对象,否则返回304。
控制缓存的能力
Cache-Control: no-store/no-cache
no-stroe禁止缓存对响应进行复制。no-cache可以存储在本地缓存器中,只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
在HTML控制缓存
<meta http-equiv="Cache-control" content="no-cache">媒体类型
Content-Type首部字段说明了实体主体的MIME类型。MIME类型由一个主媒体类型(text、image或audio等)后面跟一条斜线以及一个子类型组成。
MIME中的multipart(多部分)电子邮件报文中包含多个报文,它们合在一起作为单一的复杂报文发送。每一部分都是独立的,有各自的描述其内容的集;不同的部分之间用分界字符串连接在一起。
内容编码
Context-Encoding首部说明编码使用的算法。
Accept-Encoding首部客户端支持的编码方式。
传输编码
内容编码是对实体部分编码,而传输编码则作用在整个报文
Transfer-Encoding 告知接收方进行了何种编码
TE 告知服务器可以使用何种编码
字符
Content-Type首部中使用charset参数 或者
在HTML
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-2022-jp">重定向
HTTP重定向
客户端发送一条请求
服务器没有回送带有HTTP状态码200的Web页面主体,而是回送了一个带有状态码302的重定向报文,附有Location: 新的IP地址
客户端会用重定向URL重新发送请求,这次会发送给新的IP地址的主机
NAT
Network Address Translation 网络地址转换
交换机或其他第四层设备会检测输入分组中的TCP/IP地址,并通过修改目的IP地址,对分组进行相应的转发。