浅谈HTTP

HTTP 为什么重要


  1. HTTP 是前后端合作的重要方式
    99%的需求都是通过 HTTP 做到(如登录注册,增删改查,文件下载等),小部分需求可以通过 WebSockets 做到。
  2. HTTP 能帮你从本质上理解 HTML、CSS、JS、图片、JSON、JSONP 等不同形式的资源
  3. Web 性能优化基本等价于对 HTTP 传输效率优化
  4. 前端工程化需要你对 HTTP 缓存有深入了解

什么是 HTTP


四个概念


  1. server:JS运行在服务器上,可以监听80端口或者88端口的软件,可以接收响应,发送响应
  2. client:JS运行在客户端上
  3. request
  4. response
image.png

Unix和Linux系统中,80端口是无法被普通用户使用的,一般使用1024以上的端口,windows没有这个限制

用简单的工具了解这四个概念:

  • curl 作为 client(curl本质上跟浏览器没有区别)

    • curl 网址:可以返回response
    • curl -v 网址:会有请求和响应信息出现
    • image.png
  • server.js 作为 server

  • curl 发送一个 request 到 server.js

  • server.js 返回一个 response 给 curl

client
  1. 用户用来浏览网页的软件(GUI(图形界面) 或命令行均可)
  2. 后端开发者的爬虫
  3. 搜索引擎的爬虫

client 也可以叫做用户代理,因为它帮用户发送请求。

什么是代理?

「用户代理」的英文是 user agent,「代理」的英文是 proxy,所以并不完全一样。

通俗来说,proxy 是为了满足特定功能的 agent,这些功能包括加速访问、内容缓存、内容过滤、信息加密等;而 agent 则功能较广泛,如 Chrome 就是一个 user agent,能满足广泛的上网需求,curl 和爬虫也是 user agent,一般不能叫做 proxy。

server

server是用于提供响应的软件,一般来说一个硬件上面可以有多个软件服务器
你可以通过很多方式搭建一个 server

  1. Apache + PHP/Java/Python/Node.js
  2. Nginx + PHP/Java/Python/Node.js
  3. 只用 Node.js

正式搭建的时候使用前两种,最后那个比较脆弱

为了便于理解精髓,我们只用一个 server.js 就可以搭建一个 server,源码我已经写好了

FrankFang/nodejs-test

我们用 curl 来向这个 server 发一个请求。

curl -v http://127.0.0.1

如果你不想用 IP,可以设置一下 hosts

127.0.0.1 wtf.com
curl -v http://wtf.com
请求

请求包括四部分

  1. 第一部分 - 动词 路径 协议/版本号
  2. 第二部分 - 一堆 key: value,用回车分割
  3. 第三部分 - 回车,作用只有一个:分隔开第二部分和第四部分
  4. 第四部分 - 随便什么内容都可以,内容的格式必须要第二部分里用 Content-Type 说明

内容格式Connection-Type: application/x-www-form-urlencoded

  • x表示没有写在规范里,这个只是临时实验使用的,没有具体含义。
  • www表示是万维网
  • form代表表单格式
  • urlencoded表示是encoded过的
  • 形如xxx=yyy就是www-form-urlencoded的全部内容,多个值就是xxx=yyy&xxx2=yyy2这样,其中都是经过unicode化,是utf编码的16进制
    • 使用key=value
    • 多个key,value使用&链接
    • 特殊字符转换成百分开头的文字,如&转成%26

一般来说get请求没有第四部分,这是get和post的一个区别

curl -v 可以查看请求
Chrome 开发者工具也可以

响应

响应包括四部分

  1. 第一部分 - 协议/版本号 状态码 状态信息
  2. 第二部分 - 一堆 key: value,用回车分割
  3. 第三部分 - 回车,作用只有一个:分隔开第二部分和第四部分
  4. 第四部分 - 随便什么内容都可以,内容的格式必须要第二部分里用 Content-Type 说明

响应出现乱码的原因可能是因为没有在Content-Type中说明,并设置编码就好了

状态码一般是200-500之间的20多个,需要记忆

curl -v 可以查看响应
Chrome 开发者工具也可以

《Http权威指南》

HTML、CSS、JS 的本质


本质就是字符串,只不过 Content-Type 不同。

注意 url 里的后缀是废话,毫无意义。

  1. 浏览器通过地址栏、iframe 来请求 HTML
  2. 浏览器通过 link 标签获取 CSS,然后渲染
  3. 浏览器通过 script 标签获取 JS,然后执行
  4. 浏览器通过 image 标签获取图片,然后展示

JSON 的本质


本质就是字符串,只不过 Content-Type 为 application/json。
注意 url 里的后缀是废话,毫无意义。

请求JSON的方式:
1. 通过JS请求JSON

2.
image.png

请求每一种资源都需要使用特定的方法。
type和Content-type


image.png

使用JSON.parse可以将字符串变为对象
JSON是一个有格式的字符串,是一种语法

JSONP 的本质


本质就是字符串,只不过

  1. Content-Type 为application/javascript 或者 text/javascript
  2. 内容格式为 functionName( {"format": "JSON"} )

缓存


  1. 使用 Cache-Control 缓存是常用的缓存方式

  2. 想要更新缓存只需稍微变更一下 url

    • app-2131312362387123.js
    • app.js?v=1
    • app.js?t=201801012334
    • 不要缓存入口页面,这是你更新资源的唯一入口
  3. 前端性能优化的一个切入点就是缓存:response.setHeader('Cache-Control', 'max-age=3600')


    image.png

    image.png
  4. 我们可以看到当我们在server.js那边设置了cache-control,在后面的前端响应那边会带上这个信息

  5. 当我们再次请求这个style的时候,status的200变成灰色,size变成了(from disk cache),这个的意思就是没有去读服务器,而是从本地浏览器的缓存中读取,我们可以看到本地文件的时间没有很大差异,但是当在远程服务器上面的时候,时间差异会很大。其他没有这种cache-control设置的就得从服务器下载。我们看服务器在二次刷新的时候没有发送style文件


    image.png
  6. 缓存其实很简单,就在server.js上加了一句代码。所有的网站都是这种效果

  7. 在浏览器的开发者工具里面,点击disable cache就可以不使用之前的缓存。缓存在网络快的情况下,效果非常显著。

  8. 设置缓存的时间,时间过了之后才会再次请求服务器。

  9. 如何强制抛弃之前的缓存?可以更改之前请求的url,如在url后面写一个随机数,当这个路径跟之前的路径不一样,就会重新请求


    image.png

    image.png
  10. 我们发现有的时候缓存放在内存(memory)中,有的是放在硬盘(disk)中的。具体浏览器缓存到哪里是无法控制的


    image.png
  11. 实际过程中,百度图片默认缓存10年,意味着10年内不需要更新,在这个过程中,如果需要变化,只需要更改图片的后缀就好了,请求的url变化了,一定会再次更新;做法就是尽量设置最长的内存时间,需要更改就更改一下请求的url

  12. 重新请求的方法以及问题

    1. 我们可以在请求的文件后面添加时间,如/style?t=20200424164455
      • 问题1:有可能会在1s中改了两次文件,那么前半秒下载文件的用户得不到后半秒更改之后的文件
      • 问题2:当有多个文件的时候,手动更改的时候容易出错
      • 现在一般不使用时间戳
      • 之前没有node.js,一般更新缓存的时候会在访问路径后面添加时间戳或者更新版本号
    2. 有了node.js之后,我们一般这样写/style-md5,文件后面加一个md5,
      • md5是对文件内容去一个特殊值
      • image.png
      • md5很难重复,现在一般的做法就是后面添加一个md5,有的会加一个md5的前八位
      • image.png
      • 这样就不需要程序员自己算需要加什么样的值。
      • 只要文件变化,md5就可以变化
      • webpack内部封装了md5变化,通过设置,只要文件变化后,打包的时候就会在后面添加一个md5
    3. 一般入口文件不加缓存,因为入口文件需要记录其余文件的变化,一旦这个入口文件不变了,就意味着其余文件即便变化了我们也不知道。

并不是缓存


  1. 使用 Etag 和 304 可以避免下载过程
  2. 这并不是严格意义的缓存
  3. 设置ETag的方式如下所示,使用response.setHeader('Etag', 'frank'):


    image.png
  4. 设置好Etag之后,第一次请求之后,response里面会有一个Etag,其值就是我们设置好的值


    image.png
  5. 第二次访问的时候,浏览器会带着这个Etag的值进行请求,即If-None-Match: frank


    image.png
  6. 这是方便服务器去读取的,服务器如果拿到这个这个If-None-Match,可以拿着个跟之前设置的Etag做对比,相等就代表内容一致,不需要进行传递,就不返回内容就好


    image.png

    image.png
  7. Etag还是会请求服务器,但是如果值相同就不下载,如果文件变化之后,更改一下Etag就好,我们可以让Etag就等于Md5


    image.png

Cookie


Cookie 用于识别用户

我的知乎专栏文章

注意:

  1. 现代前端几乎不会去碰 Cookie
  2. 如果需要多页面共享信息,请用 localStorage 或 sessionStorage
  3. Cookie 的所有知识都可以用维基百科查到
  4. 我们使用简单的node.js代码就可以实现Cookie。HTTP是一种无状态协议,使用Cookie就可以让HTTP有状态
  5. 我们在首页的响应头里面写一个Cookie,就可以看到在响应的时候会有这样的值,这个cookie其实只要关闭页面就过期了


    image.png

    image.png

    image.png
  6. 我们发现我们只设置了入口文件的Cookie,并且入口文件的response里面带着的参数是set-cookie,即设置了cookie,一旦设置了cookie,后面所有文件的请求都会带着这个参数,即cookie参数,也就是请求的时候会将cookie返回给服务器


    image.png
  7. cookie就好像一个访问的权限,带着cookie可以访问一些内容,但是没有的话就不准访问,服务器可以读取这个Cookie,判断值到底对不对。


    image.png

    image.png
  8. 网页上填的东西都是以明文的形式传递的,没有任何安全性可言
  9. Cookie可以识别用户有没有曾经做过一件事情,如果做过,就种一个Cookie。我们一般将设置Cookie称为种Cookie,就是服务器的响应里面有一个set-cookie的头
  10. 登出一般是后端程序员做的事情,需要清除Cookie,一般是通过设置过期时间来的。


    image.png

Session


Session 就是 server 为用户分配的一小段内存,用户的识别依据可以用 Cookie 保存(也可以不用 Cookie)

  1. Cookie的优点是可以记住用户的状态,缺点是Cookie容易被伪造
  2. 我们的目标是技能标识用户,也能防止用户随意更改?这就是Session,Session是Cookie的升级版
  3. 我们可以定义一个session,session相当于一个账本,给浏览器的是票据,这个票据对应着用户信息,这样就不会将用户信息暴露出去了。伪造票据的几率很低的。
  4. session可以每天重新分派,里面的账户信息是可以对应上的。猜对的概率很低很低。
  5. 使用随机的32位字符作为ID的一个好处是
    • 用户不知道自己什么信息,无法自己更改
    • 想随便更改碰对的几率太低了。
  6. 真正使用Cookie的方法是将Session的ID放入Cookie中,用户每次来都通过CookieID去读取Session。Session可以放到数据库中,可以放到内存中,可以放到文件中。Session就相当于一个内部的账单
  7. 登录是一个简单的东西,但是想做好登录是比较难的,因为涉及安全性,便捷性等各种各样的问题。有的登录还可以使用JWT来做
  8. 使用简单的方法模拟Session,随机数可能不是真正的随机,如Random,这是一个假随机,很可能被黑客猜到,不建议使用random,session要存在文件或者服务器中,否则刷新后就会消失


    image.png
  9. Session和Cookie有什么区别:
    • 目的:需要标识用户之间的不同使用Cookie,JWT是另一种技术;想记录某个用户信息的时候,使用Session,Session不是用来区分用户的,而是用来记录用户的敏感信息的
    • 实现原理:Cookie在响应的时候,写一个Set-Cookie这个头就好了,Cookie是HTTP协议层里面的东西。Session跟HTTP没有关系,Session在不同的后台框架里面有不同的实现方式,存在文件,数据库里面。而Cookie是存在浏览器中的,浏览器每次请求都会将Cookie带到服务器中
    • Session一般基于Cookie,但也是可以不基于Cookie的,可以返给LocalStorage,LocalStorage不会每次都随浏览器复制到请求中,我们可以使用JS去读取这个LocalStorage,读取之后就可以放到Header中,所以不用Cookie一样可以拿到Session;Session还可以放到url参数中如/login?sessionid=0.11111

反向代理是什么


server 根据请求中的信息,将请求分发到不同的地方,此 server 即为反向代理。

  1. 以 Nginx 配置多域名网站为例
  2. 以 server.js 转发请求为例
  3. 正向代理代理客户端,反向代理代理服务
  4. FQ一般需要开个代理,这个代理其实是给客户端提供服务;


    image.png
  5. 用户发请求进来会有一个HOST,如果这个HOST是baidu就发送到baidu服务器上,这个就是Ngix反向代理,配置文件可以实现这种代理
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容