V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
eric6356
V2EX  ›  前端开发

2017 年,你还在用 JSONP 吗?

  •  
  •   eric6356 · 2017-04-04 19:43:59 +08:00 · 4688 次点击
    这是一个创建于 2819 天前的主题,其中的信息可能已经有所发展或是发生改变。

    太长不看

    JSONP 就是个 dirty hack ,吃枣药丸,能不碰就不碰。不服来辩!

    细节

    即将接手一个前端项目。
    这项目之前是用 Rails + Angular1 做的,现在我们打算把 Rails 干掉,所有数据都让前端直接从 api.example.com 取。
    后端 api.example.com 一定是我们自己 serve ,但前端的话:

    1. 可能部署 NGINX 到各个客户服的务器上
    2. 也可能是我们自己的 admin.example.com
    3. 当然更有可能同时会有好几套,这还不确定

    之前的思路是,前端判断一下其所处的环境是否支持 CORS ,不行的话用 JSONP 当做 fallback 。至于 GET 以外的请求,这边用 JSONP 模拟了一套实现,看起来相当完善,前后端都有支持。并且我们的请求都很小,似乎不用考虑 413 的问题。

    而现在我个人的想法是,无论部署在哪,都让跑这个项目的那个 NGINX 做一次 proxy_pass ,反代到 api.example.com (对应 1 ),或是反代到我们私有网络跑 api 的那台机器上(对应 2 )。这样的优点至少有:

    1. 跨域这件事情根本不存在了,也不用去考虑 CORS 的各种坑
    2. 客户方面,只需要跑 NGINX 的那台机器连得到 api.example.com 就行,跑浏览器的机器可以是纯内网环境

    缺点:

    1. 多了一次代理转发,做反代的机器机器会有额外性能开销(如果和 api 不是同一个 NGINX 的话)
    2. 本来前端所有的文件可以都交给 CDN ,现在则必须要一台服务器了

    总之在我印象中,JSONP 这玩意就是落后于时代(亦或是超前于时代)的一个 hack 。以前、现在、未来都未曾、没有、不会出现在 W3C 或是 RFC 标准中,应该被抵制才对。

    我目前还没有说服团队成员放弃 JSONP ,尤其是用 JSONP 模拟实现了一整套非 GET 请求的前辈。
    请各位 dalao 赐教。

    28 条回复    2017-04-05 11:31:00 +08:00
    nfroot
        1
    nfroot  
       2017-04-04 20:28:39 +08:00
    放弃没问题啊。

    少数赞成多数好不好 0 0
    imswing
        2
    imswing  
       2017-04-04 20:30:19 +08:00 via Android   ❤️ 1
    origin allows *
    gdtv
        3
    gdtv  
       2017-04-04 20:30:45 +08:00
    存在却合理,既然有简单的方法解决问题(虽然这个方法不标准),为何还要用复杂的方法呢(你说的 proxy_pass 的方法我觉得比 jsonp 复杂、麻烦很多很多)?
    eric6356
        4
    eric6356  
    OP
       2017-04-04 20:42:30 +08:00 via iPhone
    @imswing
    CORS 会有一些坑,比如某些企业防火墙会屏蔽 OPTIONS 请求。这我们希望尽量避免,或者至少有 fallback 。
    eric6356
        5
    eric6356  
    OP
       2017-04-04 20:48:02 +08:00 via iPhone
    @gdtv 也就 nginx 加一行配置?
    相反 jsonp 的话,因为我很可能要完全重写这个项目,所以我需要按照目前这个并不标准的方案重新实现 JSONP 模拟非 GET 请求。当然写得好的话可能也就几十行代码,或许也是一种锻炼。
    nfroot
        6
    nfroot  
       2017-04-04 21:04:43 +08:00
    “之前的思路是,前端判断一下其所处的环境是否支持 CORS ,不行的话用 JSONP 当做 fallback ”

    楼主请问一下,你有更好的办法么
    eric6356
        7
    eric6356  
    OP
       2017-04-04 21:20:33 +08:00
    @nfroot 我说了用 NGINX 做 proxy_pass ,当然如果如果把解决方式限定在浏览器端的话的话我也就没有更好的办法了。
    我是认为反代一下之后,前后端的代码都可以更简单。
    des
        8
    des  
       2017-04-04 21:31:43 +08:00 via Android
    iframe 嵌入,然后用 postMessage 去获取怎么样?
    刚刚想到的
    eric6356
        9
    eric6356  
    OP
       2017-04-04 21:46:47 +08:00
    @des 能详细说一下吗?
    是不是需要让 api.example.com 的某个接口返回某个 html ,其中有个 script 从 api 取数据,并且给 window 注册 message 事件并且在响应函数里调用 event.source.postMessage 发数据回来。
    听起来麻烦得很,而且让 api 返回 html 页面真的好么?
    des
        10
    des  
       2017-04-04 21:56:21 +08:00
    @eric6356 所以还是 CORS 好弄,实在不行用 flash 也行。。。
    SoloCompany
        11
    SoloCompany  
       2017-04-04 22:01:25 +08:00 via iPhone
    标题党

    你说的“技术”有哪一样是在 2016 才出现的?👎
    jianyunet
        12
    jianyunet  
       2017-04-04 22:12:27 +08:00
    这种情况很常见,我的选择方式通常是,如果那个 jsonp 的模拟是开源项目而且比较健康的话,就可以用,如果是需要自己造轮子的话就尽量避免
    otakustay
        13
    otakustay  
       2017-04-04 22:38:36 +08:00
    我不太理解 jsonp 这种几乎没有副作用的东西为什么就是能不碰就不碰了,不碰对你来说到底有什么好处了……
    另外用 nginx 做反代最大的问题难道不是丢 cookie 么?
    undeflife
        14
    undeflife  
       2017-04-04 22:50:56 +08:00
    也许是我没看明白,你这场景有点混乱,而场景都还没确定,先揪这么个细节是不是太早期?

    >>这项目之前是用 Rails + Angular1 做的,现在我们打算把 Rails 干掉,所有数据都让前端直接从 api.example.com 取。
    那你们另外有后端咯 那这个 rails 的作用是啥 - -#

    >>可能部署 NGINX 到各个客户服的务器上
    你们的前端代码还需要部署到客户内网 客户机还可能是纯内网环境?

    >>本来前端所有的文件可以都交给 CDN ,现在则必须要一台服务器了
    客户机有纯内网环境了,前端文件怎么能全部交给 cdn? 不是还是至少需要个能外网的机器反代吗?既然反代 server 是必要的,多加一个 api 的反代有什么问题?
    eric6356
        15
    eric6356  
    OP
       2017-04-04 22:50:59 +08:00
    不碰的理由:
    1. 不符合任何标准,应该抵制(个人感情因素)
    2. 你也说了「几乎」没有副作用
    丢 cookie 我确实没有考虑过,感谢指出。
    不过一个 RESTful 的 API ,真的需要 cookie 吗?
    eric6356
        16
    eric6356  
    OP
       2017-04-04 22:51:31 +08:00
    @otakustay
    楼上 #15
    otakustay
        17
    otakustay  
       2017-04-04 22:57:11 +08:00   ❤️ 2
    我承认如果 cors 完全可用的情况下 jsonp 并不合适,但问题就在 cors 并不完全可用,而且同样会有一定的负面影响,比如你用非 GET 的请求就会用 preflight OPTIONS request 浪费时间,你用反向代理就给自己的服务增加压力(你想想日 PV 有 3000W 的时候你什么感觉)
    这样比起来, jsonp 的副作用比 cors 小多了啊,一个函数封装以后就完全无感知了, jsonp 真正的缺点是全 GET 在安全性上守不住
    eric6356
        18
    eric6356  
    OP
       2017-04-04 23:00:07 +08:00
    @undeflife 首先感谢仔细看了这个帖子
    1. 之前一些数据是靠 Rails 查库的,另一些是 JSONP 。
    2. 一个应用可以卖给很多客户。卖给谁,怎么卖,现在应用没有开发完,自然是不确定的了咯。
    3. 抱歉这里确实没写清楚,我在目前考虑各种场景,企图用一个方案满足所有需求。

    而且你说的很对,场景没定的话很多考虑都是多余的。
    eric6356
        19
    eric6356  
    OP
       2017-04-04 23:32:26 +08:00
    @otakustay 其实我并不太明白反代到底会有多大的额外开销。
    画了张图

    A 和 B 是 example.com 自己 serve , C 和 D 是让客户 serve 。
    那么 A 和 B 相比,以及 C 和 D 相比,我们 example 这一侧的其实并没有什么区别吧?
    eric6356
        20
    eric6356  
    OP
       2017-04-04 23:41:56 +08:00
    @undeflife
    #19 图 C 就是我考虑的,前端项目可以只用 CND 的情况
    k9982874
        21
    k9982874  
       2017-04-05 00:05:55 +08:00 via iPad   ❤️ 1
    我支持 pass_proxy 的解决方案,我司正在开展的项目和你的项目差不多情况。
    sever 只提供 API 的情境下不需要考虑用户 cookie 。
    另外当用户到达反代服务器承受不了的情况下,业务服务器早挂了。
    用户到达那个数量级应该有大把的资金去增加服务器资源。
    sagaxu
        22
    sagaxu  
       2017-04-05 00:24:45 +08:00 via Android   ❤️ 1
    @eric6356 这种防火墙后面,一堆 APP 都会受影响无法工作,所以不用考虑这种情况。而且 ssl 加密后,防火墙根本不知道传输的内容,一个四核 CPU ,可以轻松承受几千万 pv 的 https 转发工作。

    更多需要考虑的,其实是 IE8 和 IE9 的兼容性问题。在初期,设计上不能轻易放弃 fallback 的能力。
    sagaxu
        23
    sagaxu  
       2017-04-05 00:26:59 +08:00 via Android
    @k9982874 nginx 代理成瓶颈的时候,融资都融几个亿了
    AntiGameZ
        24
    AntiGameZ  
       2017-04-05 01:59:18 +08:00
    @eric6356 虽然有点俗套,但是还是想问一下图是用什么方法画的,看上去很棒。
    eric6356
        25
    eric6356  
    OP
       2017-04-05 08:10:55 +08:00 via iPhone
    changwei
        26
    changwei  
       2017-04-05 08:29:26 +08:00 via Android   ❤️ 1
    @otakustay cros 同样也可以 get , jsonp 的安全问题在于提供 jsonp 数据源的服务器如果被黑或者数据源提供商自己想做一些不可描述的事情,将会影响到使用它的网站,尤其是 jsonp 的提供商如果被黑产控制,增加菠菜暗链可能还会影响 seo 。
    otakustay
        27
    otakustay  
       2017-04-05 11:13:29 +08:00
    @changwei 是我没说清楚, jsonp 最大的问题是与普通的 HTTP 请求使用同样的 GET ,无法使用 Access-Control-*这样协议级别的东西进行访问控制,导致对任何访问者是平等对待,鉴权和访问控制就必须自行实现,相对于协议来说要弱一些
    undeflife
        28
    undeflife  
       2017-04-05 11:31:00 +08:00   ❤️ 1
    @eric6356 我的观点其实和你的做法是一致的,既然可以通过 nginx 反代解决,就没有必要在代码层面复杂化,特别是因一个还不明确的未来可能有的业务点,将整个代码的设计基于 jsonp 这样一个 hack 手段上,不太适合.
    至于反代的性能损耗,没有具体请求数据的情况下,属于过早的讨论优化的问题.

    另外根据你的帖子,你们认为应用有出售的潜在可能性,那么你们会上 https 吗?会有 api 请求频次的限制吗?相比 jsonp 而言,这些更应该考虑吧?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3640 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:00 · PVG 13:00 · LAX 21:00 · JFK 00:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.