HTTP第二阶段笔记

HTTP经典五层模型

在这里插入图片描述

低三层

  • 物理层:主要作用是定义物理设备如何传输数据
  • 数据链路层:在通信的实体间建立数据链路连接
  • 网络层:为数据在结点之间传输创建逻辑链路

传输层

  • 向用户提供可靠的端到端(End-to-End)服务
  • 传输层向高层屏蔽了下层数据通信的细节

应用层

  • 为应用软件提供了很多服务
  • 构建于TCP协议之上
  • 屏蔽网络传输相关细节

HTTP三次握手

TCP提供一种面向连接的、可靠的字节流服务。面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接。

在这里插入图片描述

三次握手

当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并最终对对方的 SYN 执行 ACK 确认。

TCP三次握手的过程如下:

  1. 客户端发送SYN(SEQ=x)报文给服务器端,进入请求连接(SYN_SEND)状态。
  2. 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。SYN_RECV是指,服务端被动打开后,接收到了客户端的SYN并且发送了ACK时的状态。再
  3. 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入连接(Established)状态。

在这里插入图片描述

URI、URL、URN

URI

Uniform Resource Identifier/统一资源标志符

用来唯一标识互联网上的信息资源。URI包含URL和URN

如http://www.baidu.com

URL

Uniform Resource Locator/统一资源定位器

http://user:pass@host.com:80/path?query=string#hash,此类格式的都叫做URL,比如ftp协议

URN
  • 永久统一资源定位符
  • 在资源移动之后还能被找到
  • 目前还没有非常成熟的使用方案

HTTP报文

在这里插入图片描述

HTTP方法

  • 用来定义对于资源的操作
  • 常用有GET、POST等
  • 从定义上讲有各自的语义

HTTP CODE

  • 定义服务器对请求的处理结果
  • 各个区间的CODE有各自的语义
  • 好的HTTP服务可以通过CODE判断结果

创建一个简单的Web服务

const http = require('http')

http.createServer((req, res) => {
    console.log('req come', req.url)
    res.end('123')
}).listen(8888)
console.log('开启成功8888')

在这里插入图片描述

CORS跨域请求的限制与解决

  • server1

    const http = require('http')
    const fs = require('fs')
    
    http.createServer((req, res) => {
        console.log('req come', req.url)
    
        const html = fs.readFileSync('text.html', 'utf8')
        res.writeHead(200, {
            'Content-Type': 'text/html'
        })
        res.end(html)
    }).listen(8888)
    
    console.log('8888服务器开启成功')
    
  • server2

    const http = require('http')
    
    http.createServer((req, res) => {
        console.log('req come', req.url)
        res.end('123')
    }).listen(8887)
    
    console.log('8887服务器开启成功')
    
  • text.html

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

此时8888服务器提供了text.html的服务,但是页面内容发送了一个8887的请求,那么会出现跨域问题。如图
在这里插入图片描述

因为没有设置服务端允许跨域的头,接下来我们只要在server2中设置一下头就可以解决跨域问题了。

const http = require('http')

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

console.log('8887服务器开启成功')

CORS跨域限制以及预请求验证

允许方法

  • GET
  • HEAD
  • POST

允许Content-Type

  • text/ plain
  • multipart/form-data
  • application/x-www-form-urlencoded

其他限制

  • 请求头限制
  • XMLHttpRequestUpload对象均没有注册任何事件监听器
  • 请求中没有使用ReadableStream对象

预请求

const http = require('http')

http.createServer((req, res) => {
    res.writeHead(200, {
        "Access-Control-Allow-Origin": '*',
        //设置允许的请求头
        'Access-Control-Allow-Headers': 'X-Test-Cors ',
        //设置允许的请求方法
        'Access-Control-Allow -Methods': ' POST, PUT , Delete',
        //设置最长时间
        'Access-Control-Max -Age': '1000'
    })
    res.end('123')
}).listen(8887)

console.log('8887服务器开启成功')

缓存Cache-Control

可缓存性

  • public:任何代理服务器都可以对数据进行缓存
  • private:只有发起请求的浏览器可以缓存
  • no-cache:任何一个节点都不可以缓存

到期

  • max-age=

    • 设置时间过期,过期后再次发送请求到服务器请求信内容
  • s-maxage=

    • 在代理服务器里才生效
  • max-stale=

    • 在max-stale时间内,即使max-age时间过期,也可以使用(浏览器用不到)

重新验证

  • must-revalidate:如果缓存已经过期,需要向源服务端重新获取数据,不能直接使用
  • proxy-revalidate:缓存服务器必须在过期时在源服务器重新请求

其他

  • no-store:本地和代理不可以缓存
  • no-transform:不可以随便改动返回的内容
const http = require('http')
const fs = require('fs')

http.createServer((req, res) => {
    console.log('req come', req.url)
    if (req.url === '/') {
        const html = fs.readFileSync('text.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=200'
        })
        res.end('console.log("script loaded")')
    }

}).listen(8888)

console.log('8888服务器开启成功')

缓存验证Last-Modified和Etag的使用

在这里插入图片描述

Last-Modified

  • 上次修改时间
  • 配合If-Modified- Since或者If-Unmodified-Since使用
  • 对比上次修改时间以验证资源是否需要更新

Etag

  • 数据签名
  • 配合If-Match或者If-Non-Match使用
  • 对比资源的签名判断是否使用缓存
const http = require('http')
const fs = require('fs')

http.createServer((req, res) => {
    console.log('req come', req.url)
    if (request.url === '/script.js') {
        console.log(request.headers)
        const etag = request.headers('if-none-match')
        if (etag === '777') {
            response.writeHead(304, {
                'Content-Type': 'text/javascript',
                'Cache-Control': ' max-age=200000,no-cache',
                'Last-Modified': '123',
                "Etag": '777'
            })
            response.end('456')
        } else {
            response.writeHead(200, {
                'Content-Type': 'text/javascript',
                'Cache-Control': ' max-age=200000,no-cache',
                'Last-Modified': '123',
                "Etag": '777'
            })
            response.end('console.log("script loaded")')
        }

    }

}).listen(8888)

console.log('8888服务器开启成功')

Cookie和Session

Cookie

  • 通过Set-Cookie设置
  • 下次请求会自动带上
  • 键值对,可以设置多个

Cookie属性

  • max-age和expires设置过期时间
  • Secure只在https的时候发送
  • HttpOnly无法通过document.cookie访问
const http = require('http')
const fs = require('fs')

http.createServer((req, res) => {
    console.log('req come', req.url)
    if (request.url === '/script.js') {
        const html = fs.readFileSync('text.html', 'utf8')
        res.writeHead(200, {
            'Content-type': 'text/html',
            'Set-Cookie': ['id=123;max-age=2', 'abc=456;HttpOnly']
        })
        res.end(html)
    }

}).listen(8888)

console.log('8888服务器开启成功')

HTTP长连接

  • HTTP1.1中有6个并发的链接
  • HTTP2在一个TCP链接可以并发的发送多个请求
const http = require('http')
http.createServer(function (request, response) {
    response.writeHead(200, {
        'Content-Type': ' text/html',
        "Connection": "close",
        "Connection": "keep-alive"
    })
}).listen(8887)
console.log('8887服务器开启成功')
<!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>
    <img src="../1.png">
    <img src="../2.png">
    <img src="../3.png">
    <img src="../4.png">
    <img src="../5.png">
    <img src="../6.png">
</body>

</html>

数据协商

  • 请求(客户端)
    • Accept
      • 明确想要接收数据的类型
    • Accept-Encoding
      • 明确编码方式,限制服务端压缩方式
    • Accept-Language
      • 返回信息判断是中文还是英文
    • User-Agent
      • 判断浏览器相关信息
  • 返回(服务端)
    • Content-Type
      • 选择一种数据格式,作为真正返回的数据格式进行返回(申明)
    • Content-Encoding
      • 对应Accept-Encoding
    • Content-Language
      • 对应Accept-Language

Redirect

  • 301:永久跳转(变更),除非清除浏览器缓存
  • 302:临时跳转
const http = require("http");
const fs = require("fs");
http.createServer(function (req, res) {
    console.log("request come", req.url);
    if (req.url === "/") {
        res.writeHead(302, {
            Location: "/new",
        });
        res.end("");
    } else {
        res.writeHead(200, {
            "Content-Type": "text/html",
        });
        res.end("<div>this is content</div>");
    }
}).listen(8888);
console.log('8888服务器开启成功')

CSP

全称为Content-Security-Policy,译为内容安全策略

作用

  • 限制资源获取
  • 报告资源获取越权

限制方式

  • default-src限制全局
  • 资源类型
    • connect-src
      • 请求发向的目标的限制
    • font-src
      • 策略可以包含一个或多个源
    • frame-src
      • 可以允许一个或多个源
    • media-src
      • 可以允许一个或多个源
    • manifest-src
      • 可以允许一个或多个源
    • img-src
      • 图片可以从哪些网址上加载
    • style-src
      • 样式和脚本的资源从哪些网址上加载
    • script-src
      • 样式和脚本的资源从哪些网址上加载
    • 。。。

实例

  • 限制内联js

    const http = require("http");
    const fs = require("fs");
    
    http.createServer(function (req, res) {
        console.log("request come", req.url);
        if (req.url === '/') {
            const html = fs.readFileSync('text.html', 'utf8')
            res.writeHead(200, {
                'Content-Type': ' text/html',
                "Content-Security-Policy": "default-src http: https: "
            })
            res.end(html)
        } else {
            res.writeHead(200, {
                'Content-Type': ' application/javascript',
            })
            req.end('console.log("loaded script")')
        }
    
    }).listen(8888);
    console.log('8888服务器开启成功')
    
    <!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>
        <div>This is content</div>
        <script>
            console.log('inline js')
        </script>
        <script src="script.js"></script>
    </body>
    
    </html>
    
  • 限制只能加载某个网站的脚本,不写就是本站

    const http = require("http");
    const fs = require("fs");
    
    http.createServer(function (req, res) {
        console.log("request come", req.url);
        if (req.url === '/') {
            const html = fs.readFileSync('text.html', 'utf8')
            res.writeHead(200, {
                'Content-Type': ' text/html',
                "Content-Security-Policy": " default-src\'self\' "
            })
            res.end(html)
        } else {
            res.writeHead(200, {
                'Content-Type': ' application/javascript',
            })
            req.end('console.log("loaded script")')
        }
    
    }).listen(8888);
    console.log('8888服务器开启成功')
    
    <!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>
        <div>This is content</div>
        <script>
            console.log('inline js')
        </script>
        <script src="script.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    </body>
    
    </html>
    
  • 只能限制表单跳转本站

    const http = require("http");
    const fs = require("fs");
    
    http.createServer(function (req, res) {
        console.log("request come", req.url);
        if (req.url === '/') {
            const html = fs.readFileSync('text.html', 'utf8')
            res.writeHead(200, {
                'Content-Type': ' text/html',
                "Content-Security-Policy": "default-src \'self\'; form-action \'self\'"
            })
            res.end(html)
        } else {
            res.writeHead(200, {
                'Content-Type': ' application/javascript',
            })
            req.end('console.log("loaded script")')
        }
    
    }).listen(8888);
    console.log('8888服务器开启成功')
    
    <!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>
        <div>This is content</div>
        <form action="http://baidu.com">
            <button type="submit">点我</button>
        </form>
        <script>
            console.log('inline js')
        </script>
        <script src="script.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    </body>
    
    </html>
    

Nginx代理以及面向未来的HTTP

Nginx的下载安装

直接去官网下载Nginx下载官网

启动nginx

  • 可以用Git Bash启动(或者用命令行启动也行)
  • 找到指定文件夹下,输入命令 nginx.exe或者 start nginx,回车即可

在这里插入图片描述

在这里插入图片描述

关闭nginx

  • 输入nginx命令: nginx -s stop(快速停止nginx) 或 nginx -s quit(完整有序的停止nginx)
  • 使用taskkill: taskkill /f /t /im nginx.exe

Nginx基础代理配置

通过 include server/*.conf 来实现一个站点设置配置文件

在nginx.conf文件中include来引入其他的conf文件,实际上就是代码写在那里面,只是方便后期管理而已。

server{
    listen 80;
    server_name test.com;
    location / {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;#代理服务器去修改头的功能
    }
}

浏览器发送的请求是发送到nginx的,nginx转发,即nginx发起请求。

Nginx代理配置和代理缓存的用处

proxy_cache_path cache levels=1:2 keys_zone=my_cache:10m;

server{
    listen      80;
    server_name test.com;
    location / {
        proxy_cache my_cache;# 设置缓存
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;#代理服务器去修改头的功能
    }
}

HTTPS

加密

  • 公钥:用于加密会话密钥、验证数字签名,或加密可以用相应的私钥解密的数据
  • 私钥:单个私钥来加密和解密数据

在这里插入图片描述

HTTP2

优势

  • 信道复用
  • 分帧传输
  • Server Push
    在这里插入图片描述
    在这里插入图片描述
    http1与http2的比较
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值