原生koa2实现jsonp

前言

在项目复杂的业务场景,有时候需要在前端跨域获取数据,这时候提供数据的服务就需要提供跨域请求的接口,通常是使用JSONP的方式提供跨域接口。

实现JSONP

demo地址

https://github.com/ChenShenhai/koa2-note/blob/master/demo/jsonp/

具体原理

  1. // 判断是否为JSONP的请求
  2. if ( ctx.method === 'GET' && ctx.url.split('?')[0] === '/getData.jsonp') {
  3. // 获取jsonp的callback
  4. let callbackName = ctx.query.callback || 'callback'
  5. let returnData = {
  6. success: true,
  7. data: {
  8. text: 'this is a jsonp api',
  9. time: new Date().getTime(),
  10. }
  11. }
  12. // jsonp的script字符串
  13. let jsonpStr = `;${callbackName}(${JSON.stringify(returnData)})`
  14. // 用text/javascript,让请求支持跨域获取
  15. ctx.type = 'text/javascript'
  16. // 输出jsonp字符串
  17. ctx.body = jsonpStr
  18. }

解析原理

  • JSONP跨域输出的数据是可执行的JavaScript代码
    • ctx输出的类型应该是’text/javascript’
    • ctx输出的内容为可执行的返回数据JavaScript代码字符串
  • 需要有回调函数名callbackName,前端获取后会通过动态执行JavaScript代码字符,获取里面的数据

效果截图

同域访问JSON请求

jsonp-result-01

跨域访问JSON请求

jsonp-result-02

完整demo代码

  1. const Koa = require('koa')
  2. const app = new Koa()
  3. app.use( async ( ctx ) => {
  4. // 如果jsonp 的请求为GET
  5. if ( ctx.method === 'GET' && ctx.url.split('?')[0] === '/getData.jsonp') {
  6. // 获取jsonp的callback
  7. let callbackName = ctx.query.callback || 'callback'
  8. let returnData = {
  9. success: true,
  10. data: {
  11. text: 'this is a jsonp api',
  12. time: new Date().getTime(),
  13. }
  14. }
  15. // jsonp的script字符串
  16. let jsonpStr = `;${callbackName}(${JSON.stringify(returnData)})`
  17. // 用text/javascript,让请求支持跨域获取
  18. ctx.type = 'text/javascript'
  19. // 输出jsonp字符串
  20. ctx.body = jsonpStr
  21. } else {
  22. ctx.body = 'hello jsonp'
  23. }
  24. })
  25. app.listen(3000, () => {
  26. console.log('[demo] jsonp is starting at port 3000')
  27. })