目录
- 1 模拟跨域请求
- 2 CORS 跨域限制以及预请求验证
- 3 Cache-Control 的含义和使用
- 4 Last-Modified 和 Etag
- 5 cookie 和 session
- 6 HTTP 长连接
- 7 数据协商
- 7.1 请求
- 7.2 返回
- 8 重定向, 301 和 302
1 模拟跨域请求
curl 命令
curl www.baidu.com
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>
/* 向 8887 发送请求 */
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8887');
xhr.send();
</script>
<!-- jsonp -->
<!-- <script src="http://127.0.0.1:8887"></script> -->
</body>
</html>
service8.js
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request', request.url);
const html = fs.readFileSync('text.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text-html'
})
response.end(html);
}).listen(8888)
console.log('server listing 8888');
service7.js
/* 8887 服务允许跨域 */
const http = require('http');
http.createServer(function (request, response) {
console.log('request--8887', request.url);
response.writeHead(200, { // 允许跨域
'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'
// 'Access-Control-Allow-Origin': '*'
})
response.end('1111')
}).listen(8887)
console.log('server listing 8887');
2 CORS 跨域限制以及预请求验证
CORS 跨域默认允许的方法:
GET
POST
HEAD
而 PUT、DELETE 默认不允许跨域请求,需要先发送预请求进行验证。
跨域默认允许的 Content-Type:
text/plain
multipart/form-data
application/x-www-form-urlencoded
其他限制
- 请求头限制(自定义请求头默认不允许跨域)
Access-Control- 响应头说明
text.html,使用 fetch
<!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>
/* 向 8887 发送请求 */
fetch('http://127.0.0.1:8887/', {
method: 'PUT',
headers: {
'X-Test-Cors': '111'
}
})
</script>
</body>
</html>
service7.js,配置其他响应头字段
/* 8887 服务允许跨域 */
const http = require('http');
http.createServer(function (request, response) {
console.log('request--8887', request.url);
response.writeHead(200, { // 允许跨域
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'X-Test-Cors',
'Access-Control-Allow-Methods': 'PUT,POST,DELETE,GET,HEAD',
'Access-Control-Max-Age': '10000'
})
response.end('1111')
}).listen(8887)
console.log('server listing 8887');
Access-Control-Allow-Headers
允许自定义请求头请求跨域Access-Control-Allow-Headers
允许方法请求跨域Access-Control-Max-Age
允许在最大的时间内,浏览器不用再发送预请求
3 Cache-Control 的含义和使用
Cache-Control 是一个客户端缓存,如果服务器的资源发生改变的时候,而客户端的 url 没有改变,不知道服务器资源是否有变化,所以,还是会从客户端缓存里面直接取;
当服务端资源发生改变的时候,浏览器不知道是否改变,常见的解决方案为,在构架打包的时候,会根据资源的内容,在对应的资源后面加一段 hash 码,当下一次的内容发生改变的时候,则,重新构架打包出来的 hash 就会发生改变,客户端就会重新请求改变后的资源了,刷新客户端缓存。
-
可缓存性
public:浏览器或者中间代理服务器都可以缓存服务器返回的内容;private:只有发起请求的浏览器才能缓存,中间代理服务器不可以缓存;
no-cache:本地可以缓存,但是需要通过服务器验证,不能缓存;
-
到期(这个缓存什么时候到期)
max-age = <seconds>:设置多少秒后过期
s-maxage = <seconds>:在代理服务器生效,如果在代理服务器同时设置 max-age、s-maxage,则以 s-maxage 为主
max-stale = <seconds>:了解
-
重新验证
must-revalidate:过期之后,必须重新发送请求,不能使用缓存;
proxy-revalidate:在代理服务器设置,同 must-revalidate 一样;
-
其他
no-store:一定不能缓存
no-transform:了解
实例:
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 src="/srcipt.js"></script>
</body>
</html>
service8.js
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request', request.url);
if (request.url === "/") {
const html = fs.readFileSync('text.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text-html'
})
response.end(html);
}
if (request.url === "/srcipt.js") {
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10, public'
})
response.end('console.log("11111111")');
}
}).listen(8888)
console.log('server listing 8888');
4 Last-Modified 和 Etag
重新验证
-
Last-Modified
上次修改时间
配合 If-Modified-Since 或者 If-Unmodified-Since 使用
对比上次修改时间以验证资源是否需要更新
-
Etag
数据签名
配置 If-Match 或者 If-None-Match 使用
对比资源的签名判断是否使用缓存
实例:
service8.js
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request', request.url);
if (request.url === "/") {
const html = fs.readFileSync('text.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text-html'
})
response.end(html);
}
if (request.url === "/srcipt.js") {
const etag = request.headers['if-none-match']; // 获取客户端的设置的 Etag 签名
if (etag === '456') {
response.writeHead(304, { // 直接从缓存取
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10000, no-cache',
'Last-Modified': '123',
'Etag': '456',
})
response.end('');
} else {
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10000, no-cache',
'Last-Modified': '123',
'Etag': '456',
})
response.end('console.log("11111111")');
}
}
}).listen(8888)
console.log('server listing 8888');
5 cookie 和 session
cookie
通过 Set-Cookie 设置
下次请求会自动带上
键值对,可以设置多个
cookie 属性
max-age 和 expires 设置过期时间
Secure 只在 https 的时候发送
HttpOnly 无法通过document.cookie 访问
实例
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>
console.log(document.cookie)
</script>
<h1>content</h1>
</body>
</html>
service8.js
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request', request.url);
if (request.url === "test.com") {
const html = fs.readFileSync('text.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text-html',
'Set-cookie': ['id=123; max-age=5', 'age=12; HttpOnly; domain=test.com']
})
response.end(html);
}
}).listen(8888)
console.log('server listing 8888');
说明:
通过 Set-cookie 设置 cookie;
cookie 可以设置多个;
max-age 设置该 cookie 最长过期时间,单位秒;
HttpOnly 无法通过document.cookie 访问,安全性;
domain 设置二级域名相同的不同域可以共享 cookie;
6 HTTP 长连接
HTTP 长连接,通过设置:keep-alive
Connection: 'keep-alive'
Http 请求,是在 TCP 连接的基础之上,而使用 HTTP 长连接,可以减少 TCP 连接的建立(三次握手),提高请求速度;
7 数据协商
分类
请求
返回
7.1 请求
Accept:声明客户端想要的数据类型
Accept-Encoding:声明客户端想要类型的编码,一般指可以接受服务端返回的压缩格式,如:gzip, deflate, br
Accept-Language:声明客户端可以接受的语言;
User-Agnet:表示浏览器和系统的相关信息,移动端的浏览器跟 PC 端的浏览器是不同的,可以根据 User-Agnet,进行判断,要返回的是移动端的页面还是 PC 端的页面
说明:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Mozilla/5.0:最开始浏览器是由网景公司开发的;
(Windows NT 10.0; WOW64) :说明我的系统是 window 10,64位;
AppleWebKit/537.36:WebKit 内核,是由苹果开发的,所以必须带上;
Chrome/75.0.3770.142:Chrome 和对应的版本号;
Safari/537.36:WebKit 内核,是由苹果开发的,所以会带上 Safari 信息;
7.2 返回
Content-Type:对应 Accept,选择其中的一种作为返回格式,也就是服务端实际返回的数据格式
Content-Encoding:对应 Accept-Encoding,说明服务端具体是用什么压缩格式
Content-Language:对应 Accept-Language,说明是否是根据客户端的要求,返回想要的语言;
实例
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
const zlib = require('zlib');
http.createServer(function (request, response) {
console.log('request', request.url);
const html = fs.readFileSync('text.html');
response.writeHead(200, {
'Content-Type': 'text-html',
'Content-Encoding': 'gzip'
})
response.end(zlib.gzipSync(html));
}).listen(8888)
console.log('server listing 8888');
8 重定向, 301 和 302
301:重定向,永久性跳转,也就是通过访问 '/',确定永远都指向了 '/new';慎重!!!因为如果后面反悔了,即使服务端修改了,但是,浏览器还是会缓存之前的 301 后的地址,除非客户手动的清除数据,否则,永远都不会改变,不可控。
302:重定向,临时跳转,有可能以后,不是跳转到 '/new' 路径;
/* 读取 text.html,8888 服务 向 8887 服务 跨域请求 */
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request', request.url);
if (request.url === '/') {
response.writeHead(302, { // 重定向,临时跳转,有可能以后,不是跳转到 '/new' 路径
'Location': '/new'
})
response.end();
}
// if (request.url === '/') {
// 重定向,永久性跳转,也就是通过访问 '/',确定永远都指向了 '/new';慎重!!!
// 因为如果后面反悔了,即使服务端修改了,但是,浏览器还是会缓存之前的 301 后的地址,除非客户手动的清除数据,否则,永远都不会改变,不可控。
// response.writeHead(301, {
// 'Location': '/new'
// })
// response.end();
// }
if (request.url === '/new') {
const html = fs.readFileSync('text.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text-html',
})
response.end('this is Content');
}
}).listen(8888)
console.log('server listing 8888');