响应头
HTTP响应头(HTTP response headers)是在HTTP响应中发送的元数据信息,用于描述响应的特性、内容和行为。它们以键值对的形式出现,每个键值对由一个标头字段(header field)和一个相应的值组成。
例如以下示例
Access-Control-Allow-Origin:*
Cache-Control:public, max-age=0, must-revalidate
Content-Type:text/html; charset=utf-8
Server:nginx
Date:Mon, 08 Jan 2024 18:32:47 GMT
响应头和跨域之间的关系
- cors
跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种机制,用于在浏览器中实现跨域请求访问资源的权限控制。当一个网页通过 XMLHttpRequest 或 Fetch API 发起跨域请求时,浏览器会根据同源策略(Same-Origin Policy)进行限制。同源策略要求请求的源(协议、域名和端口)必须与资源的源相同,否则请求会被浏览器拒绝
- 发送请求
fetch('http://localhost:3000/info').then(res=>{return res.json()
}).then(res=>{console.log(res)
})
- express 编写一个get接口
import express from 'express'
const app = express()
app.get('/info', (req, res) => {res.json({code: 200})
})
app.listen(3000, () => {console.log('http://localhost:3000')
})
发现是有报错的 根据同源策略我们看到协议一样,域名一样,但是端口不一致
,端口也无法一致,会有冲突,否则就是前后端不分离的项目,前后端代码放在一起,只用一个端口,不过我们是分离的没法这么做。
这时候我们就需要后端支持一下,跨域请求资源放行
Access-Control-Allow-Origin: * | Origin
增加以下响应头
允许localhost 5500 访问
app.use('*',(req,res,next)=>{res.setHeader('Access-Control-Allow-Origin','http://localhost:5500') //允许localhost 5500 访问next()
})
结果返回
请求头
默认情况下cors仅支持客户端向服务器发送如下九个请求头
tips 没有application/json
- Accept:指定客户端能够处理的内容类型。
- Accept-Language:指定客户端偏好的自然语言。
- Content-Language:指定请求或响应实体的自然语言。
- Content-Type:指定请求或响应实体的媒体类型。
- DNT (Do Not Track):指示客户端不希望被跟踪。
- Origin:指示请求的源(协议、域名和端口)。
- User-Agent:包含发起请求的用户代理的信息。
- Referer:指示当前请求的源 URL。
Content-type: application/x-www-form-urlencoded | multipart/form-data | text/plain
如果客户端需要支持额外的请求那么我们需要在客户端支持
'Access-Control-Allow-Headers','Content-Type' //支持application/json
请求方法支持
我们服务端默认只支持 GET POST HEAD OPTIONS 请求
例如我们遵循restFui 要支持PATCH
或者其他请求
增加patch
app.patch('/info', (req, res) => {res.json({code: 200})
})
发送patch
fetch('http://localhost:3000/info',{method:'PATCH',
}).then(res=>{return res.json()
}).then(res=>{console.log(res)
})
发现报错说patch不在我们的methods里面
修改如下
'Access-Control-Allow-Methods','POST,GET,OPTIONS,DELETE,PATCH'
预检请求 OPTIONS
预检请求的主要目的是确保跨域请求的安全性 它需要满足一定条件才会触发
- 自定义请求方法:当使用非简单请求方法(Simple Request Methods)时,例如 PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH 等,浏览器会发送预检请求。
- 自定义请求头部字段:当请求包含自定义的头部字段时,浏览器会发送预检请求。自定义头部字段是指不属于简单请求头部字段列表的字段,例如 Content-Type 为 application/json、Authorization 等。
- 带凭证的请求:当请求需要在跨域环境下发送和接收凭证(例如包含 cookies、HTTP 认证等凭证信息)时,浏览器会发送预检请求。
- 尝试发送预检请求
fetch('http://localhost:3000/info',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:'xmzs'})
}).then(res=>{return res.json()
}).then(res=>{console.log(res)
})
- express
app.post('/info', (req, res) => {res.json({code: 200})
})
发现报错了
因为 application/json
不属于cors 范畴需要手动支持
'Access-Control-Allow-Headers','Content-Type'
自定义响应头
在我们做需求的时候肯定会碰到后端自定义响应头
app.get('/info', (req, res) => {res.set('xmzs', '1')res.json({code: 200})
})
前端如何读取呢?
fetch('http://localhost:3000/info').then(res=>{const headers = res.headers console.log(headers.get('xmzs')) //读取自定义响应头return res.json()
}).then(res=>{console.log(res)
})
发现是null 这是因为后端没有抛出该响应头所以后端需要增加抛出的一个字段
app.get('/info', (req, res) => {res.set('xmzs', '1')res.setHeader('Access-Control-Expose-Headers', 'xmzs')res.json({code: 200})
})
SSE技术
Server-Sent Events(SSE)是一种在客户端和服务器之间实现单向事件流的机制,允许服务器主动向客户端发送事件数据。在 SSE 中,可以使用自定义事件(Custom Events)来发送具有特定类型的事件数据。
webSocket属于全双工通讯,也就是前端可以给后端实时发送,后端也可以给前端实时发送,SSE属于单工通讯,后端可以给前端实时发送
- express
增加该响应头text/event-stream
就变成了sse
event 事件名称 data 发送的数据
app.get('/sse',(req,res)=>{res.setHeader('Content-Type', 'text/event-stream')res.status(200)setInterval(() => {res.write('event: test\n')res.write('data: ' + new Date().getTime() + '\n\n')}, 1000)
})
前端接受
const sse = new EventSource('http://localhost:3000/sse')
sse.addEventListener('test', (event) => {console.log(event.data)
})