# [网络] 开发向的 Http 讲解

计算机网络的知识点太多，一些部分又对开发没什么实质帮助，所以这里仅针对一些开发的场景做一些总结归纳

## 一、前言

首先明确一下，现在的开发涉及到`http`网络的地方绝大多数都是通过`restful API`与后端进行数据交换，所以这里仅针对`restful`来进行讲解，并且所涉及到的大多是一些与前后端请求和响应相关的知识点

## 二、AJAX 简介

`ajax`是指 " 异步`javascript`和`xml`" ，可以在不刷新页面的情况下和后端进行数据交互，由于其异步的特性，所以一般和`promise`结合使用

另外，为什么要强调 " 在不刷新页面的情况下 " 呢？因为对于非`ajax`请求，它是会刷新页面的，例如`form`表单的`action`属性，这个属性一般用于前后端不分离的项目中，将表单数据提交到`action`属性所指定的`url`处，然后页面就会跳转到该`url`

```html
<form action="http://foo.com" method="post" enctype="multipart/form-data">
    <div>
        <label for="say">What greeting do you want to say?</label>
        <input name="say" id="say" value="Hi" />
    </div>
    <div>
        <label for="to">Who do you want to say it to?</label>
        <input name="to" id="to" value="Mom" />
    </div>
    <div>
        <button type="submit">Send my greetings</button>
    </div>
</form>
```

所以，`form action`这种数据交换的方式就不属于`ajax`，这种方式在现在的前后端分离的主流场景下已不多见，现在几乎都是使用`restful API`，也就是我们常说的`get、post`等请求

## 三、CORS 和代理

浏览器默认有同源策略，即不同协议、域名、端口的请求会被认为是跨域，从而被浏览器拦截

### 1\. 代理

代理一般指前端配置一下代理服务器，这样子就是同源了，一般开发的时候在`vite`中配置`server`选项，`webpack`中配置`devServer`选项，在实际上线后则可以配置`nginx`反向代理

### 2\. CORS

`CORS`指后端开启 "跨域资源共享" ，然后它有一组特定的响应头，用于告知浏览器哪些可以被跨域请求

* `Access-Control-Allow-Origin`：表示允许跨域请求的域名
    
* `Access-Control-Allow-Headers`：表示允许的请求头
    
* `Access-Control-Allow-Methods`：表示允许的请求方法
    
* `Access-Control-Allow-Credentials`：表示是否允许携带`cookie、token`这样的凭证
    

## 四、OPTIONS 预检请求

首先将一个概念，`restful`的请求分为简单请求和复杂请求，满足如下条件之一的则称为复杂请求：

* 请求方法不为`get`或`post`
    
* 用户设置了自定义请求头
    
* `Content-Type`的类型不是`application/x-www-form-urlencoded`或`multipart/form-data`
    

当满足`CORS`并且请求为复杂请求时，会先发起一个`options`请求，询问后端是否接受本次跨域请求，后端通过设置上述的`CORS`响应头，来告诉浏览器是否允许本次跨域请求

## 五、Cookie 的使用

### 1\. cookie 简介

首先，要明白设置`cookie`是浏览器行为，只有浏览器能够设置`cookie`

然后，`cookie`分为两种：`session cookie`和`persistent cookie`，分别为可持久化和不可持久化，`session cookie`在用户关闭浏览器后，这个`cookie`就没掉了

后端在响应时可以返回一个`Set-Cookie`的响应头，通知浏览器设置`cookie`，然后每次请求后端时，浏览器都会自动使用`Cookie`请求头来携带`cookie`

### 2\. session 和 cookie 结合使用

每当浏览器第一次请求后端时，后端会创建一个`sessionID`，并保留在后端，前端的一般保存方式就是通过后端返回`Set-Cookie`的响应头，然后设置在浏览器中，当下一次请求时作为`cookie`将`sessionID`字段发回给后端

这里有一个误区，很多说法是，对于`session`，当用户关闭浏览器时，该`session`就失效了，其实这样说并不准确；对于后端，`sessionID`在创建后，会有一个有效时间，在这段时间内，它一直保留在服务器上，但是对于前端，存储`sessionID`的`cookie`基本上是`session cookie`，也就是非持久化的，当用户关闭浏览器时，这个`cookie`就没有了，当下一次浏览器发送请求时，这个`sessionID`就无法发送给后端，所以这个`session`就失效了，那如果是`persistent cookie`，就不会这样

### 3\. CORS 时的 cookie

涉及到`CORS`中使用`cookie`的有两点：

* `withCredentials`：将这个设置为`true`，可以让浏览器在跨域请求时向后端发送`cookie`，但是后端的`Access-Control-Allow-Origin`就不可以再为`*`，必须指定一个具体的源，否则只能放弃`cookie`；另外，如果不将该项设置为`true`，则后端返回的`Set-Cookie`响应头会被忽略，即浏览器不会设置`cookie`
    
* `Access-Control-Allow-Credentials`：跨域时如果发起预检请求，后端则通过这个响应头来告诉浏览器是否允许携带凭证
    

正常情况下，如果这两项都被正确设置的话，那么在跨域时是可以携带并设置`cookie`的；但是我亲测在`edge`下`CORS`时，后端的`Set-Cookie`并不生效，这可能和浏览器的不同实现有关，所以使用`cookie`时建议还是使用代理
