34·灵魂前端工程师养成-[前后分离]跨域、CORS、JSONP

2022-10-31 18:10:43 浏览数 (1)

  • 跨域

  • 同源策略
  • 代码演示
  • 跨域使用AJAX
  • 解决跨域问题方法一:CORS
  • 解决方法二:JSONP
  • 封装JSONP[扩展]

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


跨域

跨域的关键知识点:

同源策略 浏览器故意设计的一个功能限制

CORS 突破浏览器限制的一个方法

JSONP

IE时代的妥协

同源策略


什么是同源?

window.origin或location.origin可以得到当前源。

代码语言:javascript复制
window.origin
"https://www.baidu.com"

location.origin
"https://www.baidu.com"

源=协议 域名 端口号

如果两个URL的协议域名端口号完全一致,那么这两个url就是同源的

例如:

https://www.qq.com https://www.baidu.com 不同源 http://www.baidu.com https://www.baidu.com 不同源 完全一致,才算同源


同源策略定义

浏览器规定,如果JS运行在源A里,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨域访问。

例如: 架设 driverzeng.com/index.html 引用了 linuxgc.com/1.js 那么就说 1.js 运行在源driverzeng.com里 注意:这跟linuxgc.com没有关系,虽然1.js从那个域名下载。 所以1.js就只能获取driverzeng.com的数据 不能获取www.driverzeng.com或download.driverzeng.com的数据

这是浏览器的功能,浏览器故意这么设计的。

浏览器为什么这样做?

用来保护用户的隐私。

我们试想,如果没有同源策略,会怎样?

以QQ空间为例 源:https://user.qzone.qq.com 假设,当前用户已经登录(用cookie) 假设,AJAX请求/friends.json就可以获取用户好友列表 到目前为止都很正常

黑客来了 假设你的女神分析https://user.qzone-qq.com给你。 实际上这是一个钓鱼网站,你点开这个网页,这个网页也去请求你的好友列表 https://user.qzone.qq.com/friends.json 请问,你的好友列表是不是就就被黑客,偷摸的偷走了?


问题的根源

无法区分发送者 QQ空间面里的JS和黑客网页里面的JS发的请求几乎没有区别(Referer有区别),如果后台开发者没有检查referer那么就完全没有区别。所以,没有同源策略,任何页面都能偷QQ空间的数据,甚至支付宝余额

那检查referer不就好了? 安全原则,安全链条的强度取决于最弱一环,万一这个网站后端开发,是一个傻X呢?所以浏览器应该主动预防这种投数据的行为,总之,浏览器是为了用户隐私,设置了严格的同源策略。

同源策略总结:不同源的页面之间,不准互相访问数据

代码演示

创建两个网站:

qq-com里面有一个server.js,用来模拟QQ空间。 driverzeng-com里面有一个server.js,用来模拟坏人网站

qq-com: /index.html 是首页 /qq.js 是JS脚本文件 /friend.json 是模拟好友数据 端口:8888 URL:http://127.0.0.1:8888

打开qq-com目录,里面创建server.js文件,写入代码

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(`
        <!DOCTYPE html>
        <head>
            <link rel="stylesheet" href="/x">
        </head>
        <body>
            <h1>曾老湿</h1>
            <script src="/y"></script>
        </body>
    `)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else if(path === '/y'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(`console.log('这是JS内容')`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

zls-com: /index.html 是首页 /zls.js 是JS脚本文件 端口:9999 URL:http://127.0.0.1:9999

打开zls-com目录,里面创建server.js文件,写入代码

启动服务,创建两个终端:

先创建QQ,启动服务

代码语言:javascript复制
MacBook-pro:qq-com driverzeng$ node-dev server.js 8888

再创建ZLS,启动服务

代码语言:javascript复制
MacBook-pro:zls-com driverzeng$ node-dev server.js 9999

打开浏览器分别访问:

http://127.0.0.1:8888

http://127.0.0.1:9999


完善QQ页面

server.js

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

index.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QQ空间</title>
</head>
<body>
    欢迎来到xxx的QQ空间
</body>
</html>

qq.js

代码语言:javascript复制
console.log('qq.js')

friends.json

代码语言:javascript复制
[
    {"name":"邓紫棋"},
    {"name":"吴彦祖"},
    {"name":"彭于晏"},
    {"name":"周杰伦 "}
]


完善zls页面

server.js

代码语言:javascript复制

index.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>曾老湿 黑客网站</title>
</head>
<body>
    说了你可能不信,我特么的是黑客
</body>
</html>

zls.js

代码语言:javascript复制
console.log('zls')

跨域使用AJAX

正常使用AJAX,在qq.com:8888里运行JS可以访问到/friend.json

index.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QQ空间</title>
</head>
<body>
    欢迎来到xxx的QQ空间
    <script src="qq.js"></script>
</body>
</html>

qq.js

代码语言:javascript复制
const request = new XMLHttpRequest()
request.open('GET','friends.json')
request.onreadystatechange = () => {
    if(request.readyState === 4){
        if(request.status >= 200 && request.status < 400){
            console.log(request.response)
        }
    }
}
request.send()

黑客偷数据,在zls.com:9999里运行JS,不能访问!浏览器需要CORS

index.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>曾老湿 黑客网站</title>
</head>
<body>
    说了你可能不信,我特么的是黑客
    <script src="zls.js"></script>
</body>
</html>

zls.js

代码语言:javascript复制
const request = new XMLHttpRequest()
request.open('GET','http://127.0.0.1:8888/friends.json')
request.onreadystatechange = () => {
    if(request.readyState === 4){
        if(request.status >= 200 && request.status < 400){
            console.log(request.response)
        }
    }
}
request.send()

解决跨域问题方法一:CORS

问题根源,浏览器默认不同源之间不能相互访问数据,但是qq.com和zls.com都是我的网站,我是老板,我就想让两个公司的资源做共享,你作为一个浏览器,你凭阻止?

浏览器:emmm... 那行吧,那我给你一个方法,你要是想共享数据,那就需要提前声明。

哦?是吗?那我要怎么声明呢?

浏览器:你要跟qq.com这个网站说一声,在响应头里写上zls.com可以访问。

哦?是吗?那具体语法呢?

浏览器:Access-Control-Allow-Origin:http://zls.com mmp,都在文档里,不好去MDN看吗?

走起,后台服务设置一波:

server.js

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

解决方法二:JSONP

有了第一种解决办法,为啥还需要第二种呢?是因为第二种方法更好么?

这个时候IE浏览器不得不问你一句话:你猜,我支不支持CORS?

Fuck,这还用猜?IE 6 7 8 9,白扯,前端开发的噩梦,兼容IE。

老板:我特么的就要兼容IE。

你:...我(qu)这(ni)就(da)去(ye)做(de)


JSONP

定义

JSONP跟JSON半毛钱关系都没有,由于前端水平低下,错误的将其称为JSONP

面临问题

程序猿常常面临奇葩需求 没有CORS,怎么跨域? 记不记得我们可以随意引用JS 虽然我们不能 访问qq.com:8888/friends.json 但是我们能引用qq.com:8888/friends.json啊 这有什么用?JS又不是数据 我们让JS包含数据不就好啦?试试看吧,明天就要上线了。

首先我们在qq.com中创建一个friends.js

先占个位,然后在server.js中添加路由

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    const string = fs.readFileSync('public/friends.js').toString()
    const data = fs.readFileSync('public/friends.json').toString()
    const string2 = string.replace('{{ data }}',data)
    response.write(string2)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

可以发现,这并不是一个合法的JS,这个只是数据,所以我们需要在friends.js里面加上一赋值

代码语言:javascript复制
window.zls = {{ data }}

这才是一个合法的JS,然后我们使用zls.js调用JS

代码语言:javascript复制
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
document.body.appendChild(script)

我们还可以监听JS的onload事件

代码语言:javascript复制
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

一开始我说,这个跟JSON一点关系都没有,为啥呢?因为我们可以把数据改成别的,不一定非得是JSON,可以是XML,HTML...

friends.js

代码语言:javascript复制
window.zls = `<xml>曾老湿</xml>`

那是不是就可以叫,XMLP?

那如果里面的数据是3呢?

代码语言:javascript复制
window.zls = 3

卧槽,细思极恐~~~~~~~~ 不知道该叫啥。不知所措。

话说回来,CORS的方法,可以设置白名单,指定谁能访问,还是挺安全的,但是...JSONP没有办法指定啊。mmp,这怎么搞?那我们就只能从判断referer开始入手了。

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)


优化

window.zls 这样不就写死了么?那空间还有其他函数调用朋友的名字,比如,最近访客,比如,评论的人,比如,好友生日...

所以我们要定义一个随机数给函数,给url添加一个查询参数

zls.js

代码语言:javascript复制
const random = Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

server.js

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        console.log(query.functionName)
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

这样一来,我们查询参数和后台的server.js就可以配合了,然后我们在后台,获取到这个functionName,做个替换。

friends.js

代码语言:javascript复制
window['{{ zls }}'] ({{ data }})

server.js

代码语言:javascript复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:'   pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data).replace('{{ zls }}',query.functionName)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 '   port   ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:'   port)

这样每次都是随机数了,就不会被写死了。但是也可能随机会随机到相同的或者跟别的开发,'撞衫'了,怎么办呢?

那我们就在随机数前面加一个前缀,保证不会重复

zls.js

代码语言:javascript复制
const random = 'zlsFunctionNameJSONPbalala' Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

问题又来了,我们每发一次请求,就会多加载一个js文件。

怎么办呢?我们既然能创建script也能删除。

代码语言:javascript复制
const random = 'zlsFunctionNameJSONPbalala' Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    script.remove()
}
document.body.appendChild(script)

这个就叫做...过河拆桥,emmm... 我们先创建script,拿到数据后,我们就可以把它删掉了。

封装JSONP[扩展]

代码语言:javascript复制
function  jsonp(url){
    return new Promise((resolve,reject)=>{
        const random = 'zlsFunctionNameJSONPbalala' Math.random()
        window[random] = (data) =>{
            resolve(data)
        }
        const script = document.createElement('script')
        script.src = `${url}?functionName=${random}`
        script.onload =  () =>{
            script.remove()
        }
        script.onerror = ()=>{
            reject()
        }
        document.body.appendChild(script)
    })
}

使用jsonp

代码语言:javascript复制
jsonp('http://127.0.0.1:8888/friends.js')
    .then((data)=>{
        console.log(data)
    })

0 人点赞