Posted in

今天实现了一个不一样的跨域方案_AI阅读总结 — 包阅AI

包阅导读总结

1.

关键词:低代码平台、接口跨域、转发接口、后端实现、解决方案

2.

总结:小伙伴在使用低代码平台 marsview 搭建页面时遇到接口跨域问题,由于诸多常规方案不可用,最终通过开发后端转发接口解决,前端进行相应配置修改,经线上验证有效,此思路为解决跨域问题提供了新方法。

3.

– 问题背景

– 小伙伴使用低代码平台 marsview 搭建页面时发现接口跨域问题。

– 因低代码的特殊性,常用跨域方案无法使用。

– 解决方案

– 开发转发接口,由后端实现接口转发,透传参数和请求头信息。

– 前端配置接口时开启代理,修改请求拦截器。

– 后端实现

– 封装 request 类,处理 get 和 post 请求。

– 定义服务访问路由,处理 get 和 post 请求的参数和返回值。

– 线上验证

– 拖拽按钮配置事件流调用第三方登录接口,发送请求成功。

– 测试 post 请求成功,解决了跨域问题。

– 总结

常规跨域方案在某些情况下难以实施,此低代码平台跨域问题解决思路具有较好效果。

思维导图:

文章地址:https://juejin.cn/post/7408775736797200418

文章来源:juejin.cn

作者:河畔一角

发布时间:2024/8/31 13:18

语言:中文

总字数:1854字

预计阅读时间:8分钟

评分:90分

标签:跨域问题,低代码平台,接口转发,前端开发,后端开发


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

背景

最近小伙伴在使用低代码平台marsview搭建页面时,发现一个接口跨域问题。

当在marsview创建的页面里面,配置第三方接口时,由于第三方接口不支持跨域,导致低代码页面请求报错,这个问题怎么处理? 如果不解决,可能用户就无法使用这个平台来搭建页面了。

于是,我思考了一下,跨域虽然有很多方案,但是,由于低代码的特殊性,很多方案是无法使用的,比如:nginx反向代理,后端设置CORSiframeJSONP等等。

为什么不能用? 因为低代码配置的第三方接口都是不确定的,你不知道用户会添加什么接口,也就无法再nginx里面做反向代理,同时第三方的接口我们并没有自主权,对方未必会配合我添加CORS,那我该怎么办?

解决方案

既然搭建是基于marsview低代码平台搭建的页面,那问题自然由低代码平台解决,我的方案是开发一个转发接口,由自己的后端去实现接口转发,把参数、请求头等关键信息全部透传过去,毕竟后端调用后端不会出现跨域问题,最终把第三方接口返回的值再返回给低代码平台。

image.png

上面是实现功能前,低代码配置的第三方接口跨域报错截图。

前端实现

一、前端配置接口时,开启接口代理。

image.png

其他配置方式都不变,只需要开启代理配置即可。

二、修改请求拦截器

instance.interceptors.request.use((config) => {  ...  config.headers = {    ...config.headers,    proxyApi: config.isCors ? config.url : '',  };    if (config.isCors) {    config.url = `${import.meta.env.VITE_BASE_API}/ai/proxy`;  }  ...  return config;});

这里面有几个关键信息。

  • 当开启代理后,拦截器中的config会拿到一个isCors参数,我们获取到第三方接口的请求地址添加到请求头中,字段定义为:proxyApi
  • 修改当前接口的url为自己后端的转发接口。也就是让当前的请求调用自己的后端接口。

前端一共就修改这两处即可,剩下的就交给后端处理。

后端实现

假设你已经会使用Koa开发服务,我们定义一个代理接口,来实现第三方接口转发。

一、简单封装一个request

const { Axios } = require("axios");class Request {  constructor(config) {    this.instance = new Axios({      baseURL: config.baseURL || "",      timeout: 8000,      timeoutErrorMessage: "请求超时",      withCredentials: true,      headers: {        "Content-Type": "application/json",      },    });  }  get(url, params, config = {}) {    return this.instance.get(url, { params, ...config });  }  post(url, params, config = {}) {    return this.instance.post(url, params, config);  }}module.exports = new Request({});

封装两个常用的getpost请求,把参数和配置都提前处理好。比如get使用paramspost直接传参数,另外增加一个自定义的config以防后期参数扩展。

二、定义服务访问路由

router.get("/proxy", async (ctx) => {  try {    const {      query,      headers: { host, proxyapi, ...headers },    } = ctx.request;    const response = await request.get(proxyapi, query || {}, {      headers,    });    const res = JSON.parse(response.data);    ctx.body = res;  } catch (error) {    util.fail(ctx, 500, "接口请求失败");  }});

我们先定义一个get路由,这里有几个关键信息。

  • get请求,从query里面拿到当前平台接口调用的参数。
  • 从请求头拿到代理地址和请求头的其它参数,比如:proxyapiauthorization等字段。这里前端虽然传的是大写,但后端获取的请求头均为小写。
  • 请求头需要排除host字段,这个如果加进去,会影响服务调用。
  • 把第三方接口返回值输出给前端。

三、定义POST请求

为了保证不管是get还是post接口都能实现转发,我们需要复制一个post请求。

router.post("/proxy", async (ctx) => {  try {    const {      body,      headers: { host, proxyapi, ...headers },    } = ctx.request;    const response = await request.post(proxyapi, JSON.stringify(body || {}), {      headers,    });    const res = JSON.parse(response.data);    ctx.body = res;  } catch (error) {    util.fail(ctx, 500, "接口请求失败");  }});

get基本一样,只是取值有变化,post请求需要从ctx.request.body取值,另外针对参数需要通过JSON.stringify(body || {})转一下。

线上验证

一、拖拽一个按钮,配置一个事件流,调用一个第三方登录接口

image.png

image.png

二、点击后通过事件流,发送请求

image.png

image.png

我们会发现,平台发送出去的接口是:/api/ai/proxy,同时在请求头中添加了proxyApi参数,值为第三方接口地址,接口返回了对应的数据。

三、测试post请求

  1. 添加第三方post接口地址,开启代理配置。

image.png

  1. 配置按钮的事件流

image.png

  1. 点击发送请求测试

image.png

我们看到发送了一个post请求出去了,地址是我们开发的后端代理服务。

image.png

第三方接口也返回了数据,说明本次低代码平台第三方接口跨域问题解决。

总结

有时候,前端很无奈,跨域其实是一个非常小的问题,惯用的做法就是后端设置一下access-control-allow-origin就可以了,但是由于服务端不愿意加或者服务端统一走的公司网关,自己代码加的不起作用,就需要在网关层加配置,但是网关层可能加起来比较麻烦,最终就不了了之了。

还有一个常用的就是nginx反向代理,小公司可能还好,找运维加一下就OK,但是大体量的公司,一般可能找运维处理这些问题会比较麻烦,因为可能都不知道运维是谁。

所以,本次低代码搭建的过程,觉得这个思路挺好,以后就能彻底解决跨域问题了,也不用去求别人了。