问题来源
期末的一个作业,我和同学打算建一个前后端分离的 Web 项目。他用 java 写了一个 api server,而我则构建前端。
我们的 api 抄了别人的一套设计,但只有自己实现的接口遇到了跨域资源请求被禁止的问题。
经过一番调查,我发现别人的接口获取的数据其实是 jsonp
格式,只是文档里让你看起来像获取 json
一样。
jsonp 和 json
我翻开 《JSON 必知必会》
发现发现其 6.3.2
小节有介绍 jsonp
。
json
我就不多讲了,我们看看 jsonp
是怎么一回事。
我们用 jQuery
向服务发起一个 ajax
请求 jsonp
数据(注意 dataType
字段):
$.ajax({ method: 'GET', url:"http://localhost:3000/login", dataType:"jsonp", data: { userid: that.userid }, success(data, status, xhr) { console.log(data); } })
浏览器实际向服务器发起的请求 url 是这样的(注意 callback
这个查询参数):
http://localhost:3000/login?userid=h&callback=jsonp
从服务器返回的参数竟然是一段 javascript
代码:
jsonp({ "success": false, "code": 13 });
原来, jsonp
是这么工作的:它通过动态地向页面插入 <script>
的方式获取数据。
我们使用的 jQuery
库的函数做好了很多工作,让它感觉和获取 json
一样。(js原生写法可以看《JSON 必知必会》6.3.2)
既然知道是怎么一会事了,我该如何补救呢?
解决办法
1. 改 java 服务器端代码
这个方法很现实,不过:
- 老实说我 java 已经不会写了,其对于我来说是 Readonly。
- 找同学修改,不太好意思呢。
2. 做个转换的中间层
对于我个准前端来说,还是 node.js
最友好。
实现思路大致如下:
-> 获得请求 -> 所有请求转发 java 服务器 -> 从 java 服务器获得的 json 并包装成 callback(json),也就是jsonp -> 回复
像这个样子:
--------------- 请求JSONP --------------- 请求JSON --------------- | |------------------>| json |------------------>| | | 浏览器 | | to | | 服务器 | | |<------------------| jsonp |<------------------| | --------------- 答复JSONP --------------- 答复JSON ---------------
原来我的想法是通过 node 的原生 api 来做,后来想起原来一直拿来做静态 api server 的 json-server 模块,结果寥寥几行代码就搞定了:
var server = require('json-server')(); var request = require('request'); var serverUrl = 'http://the.url.of.json.server'; server.get('*', function (req, res) { request(serverUrl + req.url, function (error, response, body) { res.jsonp(JSON.parse(response.body)); }); }); server.listen(3000);
(同学 api 实现得不太好,错误的参数会返回 tomcat 的 html 页面,所以我是做了错误处理以防崩溃,上面代码简便起见不处理了)
json-server
还有提供网页资源的功能,如果页面是这里提供,那么直接转发 json
也是可以的,不跨域了嘛。
总结
最后再啰嗦点其他东西:
-
我觉得别人的 API 是这样设计的:当请求参数有
callback
时答复jsonp
,没有则是json
,这样服务器可以多端通用啦!这个参数取名叫callback
难道是业界通用? -
其实跨域也不是只有
jsonp
一种办法,还有更安全的 跨域资源共享(cross-origin resource sharing,CORS) 技术,也在《JSON 必知必会》6.3 里。 - 我为什么要写这篇文章呢?这里其实没什么技术含量,只是我网上一搜全是 Java、PHP 服务器上的方法,那就不是很容易看明白。难道遇到这问题最多的不是前端程序员吗?
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。