mk_http

五层模型

浏览器从输入url到http请求返回的过程

http发展历史

http/0.9:

1.只有get命令

2.没有HEADER等描述数据的信息

3.服务器发送完毕,就关闭tcp链接

http/1.0:

1.增加了很多命令,如:post

2.增加status code 和header

3.多字符集支持,多部分发送,权限,缓存等

http/1.1:

1.持久链接

2.pipline

3.增加host和其他一些命令

http/2.0

1.所有数据以二进制传输

2.头信息压缩以及推送等提高效率的功能

3.同一个链接里吗发送多个请求不再需要按照顺序

跨域

// server.js
const http = require('http')
const fs = require('fs')

http.createServer((req,res) => {
    console.log('url',req.url)
    const html =fs.readFileSync('../test.html','utf8')
    res.writeHead(200,{
        "Content-Type": "text/html"
    })
    res.end(html)
}).listen(8888)
// server2.js
const http = require('http')

http.createServer((req,res) => {
    res.end('123')
}).listen(8887)
// test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let xhr = new XMLHttpRequest()
        xhr.open('GET','http://127.0.0.1:8887')
        xhr.send()
    </script>
</body>
</html>

1.分别用node运行server.js和server2.js,可以看到跨域了。

2.在server2.js中加入cors,来解决跨域

const http = require('http')

http.createServer((req,res) => {
    // cors解决跨域
    res.writeHead(200,{
        "Access-Control-Allow-Origin":'*'
    })
    res.end('123')
}).listen(8887)

3.通过jsonp解决跨域,利用script标签的src属性运行跨域

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
    <script src="http://127.0.0.1:8887"></script>
</body>
</html>

cors预请求:

允许方法:

get

post

head

允许Content-Type:

text/plain

Multipart/form-data

Application/x-www-form-urlencoded

其他限制:

请求头限制

1.自定义请求头

  <script>
       fetch('http://127.0.0.1:8887',{
           method:'PUT',
           headers:{
               'X-TEST-CORS':'123'
           }
       })
    </script>

服务端没做处理,会报错。

解决方法:服务端加上请求头

 res.writeHead(200,{
        "Access-Control-Allow-Origin":'*',
        "Access-Control-Allow-Headers":'X-TEST-CORS', // 请求头
 })

2.使用除了get post head方法,比如put请求

  <script>
       fetch('http://127.0.0.1:8887',{
           method:'PUT',
           headers:{
               'X-TEST-CORS':'123'
           }
       })
    </script>

服务端没做处理,会报错。

解决方法:服务端加上请求方法

 res.writeHead(200,{
        "Access-Control-Allow-Origin":'*',
        "Access-Control-Allow-Headers":'X-TEST-CORS',
        "Access-Control-Allow-Methods":'POST,PUT,DELETE', // 加上允许的方法
    })

缓存:

Cache-Control:

public:

private:只有发起请求的浏览器才可以进行缓存

No-cache:不允许进行缓存

Max-age = 1000ms 过期时间

举例:

<script src="/script.js"></script>
// server.js
const http = require('http')
const fs = require('fs')

http.createServer((req,res) => {
    console.log('url',req.url)
    if(req.url === '/'){
        const html =fs.readFileSync('../test.html','utf8')
        res.writeHead(200,{
            "Content-Type": "text/html"
        })
        res.end(html)
    }
        // 不加Cache-Control
    if(req.url === '/script.js'){
        res.writeHead(200,{
            "Content-Type": "text/javascript",

        })
        res.end('console.log("script loaded")')
    }
}).listen(8888)

加缓存:


const http = require('http')
const fs = require('fs')

http.createServer((req,res) => {
    console.log('url',req.url)
    if(req.url === '/'){
        const html =fs.readFileSync('../test.html','utf8')
        res.writeHead(200,{
            "Content-Type": "text/html"
        })
        res.end(html)
    }

    if(req.url === '/script.js'){
        res.writeHead(200,{
            "Content-Type": "text/javascript",
            'Cache-Control':'max-age = 20' // 加缓存
        })
        res.end('console.log("script loaded")')
    }
}).listen(8888)

加完缓存后,下次读取js文件就可以从缓存中读取,更快。

如果更新了js文件,但是如果缓存时间设置过长,url没改变,还是会从缓存中读取,导致代码没有更新。

解决办法:每次打包后给文件名加上hash。

Cache-Control还可以添加其他头:

'Cache-Control':'max-age = 20, public ' // 其他属性往后加就行

缓存策略:

Last-Modified:

1.上次修改时间

2.配合If-Modified-Since或者If-Unmodified-Since使用

3.对比上次修改时间来判断资源是否需要更新

Etag:

数据签名

配合If-Match

对比资源的签名判断是否使用缓存

使用:

1.将max-age调大,同时设置no-cache,允许浏览器一直访问服务器

2.设置’Last-Modified’:’123’,

3.设置’Etag’:’999’,

// server.js
if(req.url === '/script.js'){
        res.writeHead(200,{
            "Content-Type": "text/javascript",
            'Cache-Control':'max-age = 20000000,no-cache',
            'Last-Modified':'123',
            'Etag':'999',
        })
        res.end('console.log("script loaded")')
}

当第一次访问的时候,response headers就会带上上面三个头

当第二次访问的时候,request headers就会带上If-Modified-SinceIf-None-Match:来验证是否需要更新

当不需要更新的时候,服务器不用返回任何内容,下面做下修改:

if(req.url === '/script.js'){
        const e_tag = req.headers['if-none-match']
        // 命中缓存
        if(e_tag === '999'){
            res.writeHead(304,{
                "Content-Type": "text/javascript",
                'Cache-Control':'max-age = 20000000,no-cache',
                'Last-Modified':'123',
                'Etag':'999',
            })
            res.end('')
        }else{
            res.writeHead(200,{
                "Content-Type": "text/javascript",
                'Cache-Control':'max-age = 20000000,no-cache',
                'Last-Modified':'123',
                'Etag':'999',
            })
            res.end('console.log("script loaded")')
        }

    }

做了一上修改,当第一次访问时:

1.状态码为200

2.返回有值:

当第二次访问时:

1.状态码为304

2.并且也返回了内容:

3.但是在代码里没有返回内容,所以浏览器从缓存中 读取了数据

cookei和session:

cookie属性:

1.max-age和expires设置过期时间

​ max-age:过期时间

​ expires:到什么时间点过期

2.Secure只在https的时候发送

3.HttpOnly无法通过document.cookie访问

设置cookie

const http = require('http')
const fs = require('fs')

http.createServer((req,res) => {
    console.log('url',req.url)
    if(req.url === '/'){
        const html =fs.readFileSync('./test.html','utf8')
        res.writeHead(200,{
            "Content-Type": "text/html",
            'Set-cookie':"id=123" // 设置cookie
        })
        res.end(html)
    }

}).listen(8888)

第一次访问,response headers设置cookie

第二次访问,request headers就会带上cookie

nodejs设置多个cookie:

'Set-cookie':['id=123','name=aaa']

nodejs设置cookie过期时间:2s后id=123就没了

'Set-cookie':['id=123;max-age = 2','name=aaa']

设置HttpOnly:js就不能访问name=aaa了

'Set-cookie':['id=123;max-age = 2','name=aaa; HttpOnly']

长链接

Connection: keep-alive默认长链接

Connection:close关闭长链接

数据协商

Accept:

Accept-Encoding:gzip

const http = require('http')
const fs = require('fs')
const zlib = require('zlib')

http.createServer((req,res) => {
        const html =fs.readFileSync('./test.html')
        res.writeHead(200,{
            "Content-Type": "text/html",
        })
        res.end(zlib.gzipSync(html)) // 使用zlib


}).listen(1111)

Accept-Language:zh-CN

User-Agent:浏览器信息

Content:

Content-Type

Content-Encoding

Content-Language

Redirect

const http = require('http')
const fs = require('fs')

http.createServer((req,res) => {
        const html =fs.readFileSync('./test.html','utf8')
        // 302临时重定向
        // 301永久重定向
        if(req.url === '/'){
            res.writeHead(302,{
                'Location':'/new'
            })
            res.end('')
        }
        if(req.url === '/new'){
            res.writeHead(200,{
                "Content-Type": "text/html",
            })
            res.end('<div>111</div>')
        }
}).listen(2222)

csp

CSP内容

nginx

/usr/local/etc/nginx

http2

信道复用

分帧传输

server push


   转载规则


《mk_http》 朝飞 采用 知识共享署名 4.0 国际许可协议 进行许可。
 本篇
mk_http mk_http
五层模型 浏览器从输入url到http请求返回的过程 http发展历史http/0.9:1.只有get命令 2.没有HEADER等描述数据的信息 3.服务器发送完毕,就关闭tcp链接 http/1.0:1.增加了很多命令,如:post 2.
2020-06-25
下一篇 
interview-big-company interview-big-company
蚂蚁、字节、滴滴面试经历总结蚂蚁、字节、滴滴面试经历总结 微信/阿里/头条微信/阿里/头条 面试阿里P6总结面试阿里P6总结 社招7家大厂&独角兽社招7家大厂&独角兽 一位前端小姐姐的五万字面试宝典一位前端小姐姐的五万字面试
2020-06-22
  目录