AXIOS 跨域连接tms sparkel xdata服务器
XData 服务和sparkel 服务分别为tms bs中的组件,本人一直在使用。
使用vue axios组件一直无法连接两个服务器,无奈后台已经长期使用这两个服务器了,只能axios来配合解决,笔者在使用过程中遇到了以下的问题:
1: axios 如何跨域访问sparkel服务器。
2: axios 如何跨域访问xdata服务器。
3: vue.js 数据需要Json嵌套需要转义功能。
涉及服务器的组件分别为SparkleStaticServer,XDataServer
问题需要一个个解决,
问题1解决:
1): 需要修改Sparkel源码,sparkles源码中Sparkle.Module.Static.pas文件中下图类中
添加如下的几行即可
C.Response.Headers.AddValue('Access-Control-Allow-Origin','*'); C.Response.Headers.AddValue('Access-Control-Allow-Methods','GET,PUT,POST,DELETE,OPTIONS'); C.Response.Headers.AddValue('Access-Control-Allow-Headers','content-type'); C.Response.Headers.SetValue('access-control-max-age', '1728000');
2): vue.js中axios的测试代码如下
<script> const ts_url = 'http://192.168.1123:20089'; new Vue({ el: "#app", data: { title: 'ts_title' }, created() { axios.defaults.baseURL = ts_url ; axios.get('/static/1.json') .then(res => { console.log(res.data) }) .catch(err => { console.error(err); }); }, }) </script>
问题1完美解决。
问题2的解决:
1): 看了XData的源码,发现本身源码具有CROS的代码,只是调试了几次折腾了3个小时发现依然达不到我要的效果,不知道怎么用的,还是修改源码来得快一些,修改XData中源码XData.Module.Base.pas中如下图
2): 使用axios的代码进行调试
<script> const ts_url = 'http://192.168.1123:20089'; new Vue({ el: "#app", data: { title: 'ts_title' }, created() { axios.defaults.baseURL = ts_url ; var jsons = {}, qjson_data = {}; qjson_data['Permiss'] = 'Admin;XPlay'; qjson_data['Fun'] = 'GetPermissListSign'; q_str = JSON.stringify(qjson_data); jsons['QJson'] = qjson_data; //Json转义 axios.post('/Server/Manage/AppManageClassFun', jsons, { headers: { 'Authorization': 'Basic VEhJTktTSUdOOjIwMTUxMTEz' } }) .then(res => { console.log(res.data) }) .catch(err => { console.error(err); }); }, }) </script>
结果发现不管我怎么调试,出现的现象都是获取不到文件,然而我直接在浏览器中使用链接确实可以的,一直找不到问题所在,网络找了3小时,没有结果,经过一天思考各方面测试后才发现原来是我增加,http中增加了Authorization,浏览器默认先发送了OPTIONS的包,主要原因是为了服务器的安全,详细见下面网址,
https://segmentfault.com/q/1010000010159122?sort=created https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
无奈,查了下数据发现XDATA在客户端发送OPTIONS的时候提示客户端需要验证,可是尝试修改AXIOS增加HEAD到OPTIONS中去,没有找到任何方法增加,看来还是改服务器吧,然后服务器还是ProcessRequest方法,修改如下,当发送OPTINS包的时候去掉验证好了。
procedure TXDataBaseModule.ProcessRequest(const C: THttpServerContext); var Context: TXDataBaseRequestHandler; begin if C.Request.Method<>'OPTIONS' then begin if (UserName <> '') and (Password <> '') then begin if not FBasicAuthentication.Authenticate(C) then begin C.Response.StatusCode := 401; C.Response.Headers.SetValue('www-authenticate', 'Basic'); Exit; end; end; end; Context := CreateBaseHandler(C); try Context.ProcessRequest; finally Context.Free; end; end;
在使用AXIOS进行测试,发现验证可以过了,请求的数据异常。查了下XData发现原来是前端过来的JSON 数据嵌套的问题,正常XData接收的第二层JSON数据必须要有转义符'\'。
问题3解决
1: 尝试各种JS中各种JSON方法,均无果,去百度搜索,完全文不对题。难道是想让我进行字符串替换吗?
2: 还是静下心来看书吧,看了半天书,终于知道只要两次序列化就可以,哎!
<script> const ts_url = 'http://192.168.1123:20089'; new Vue({ el: "#app", data: { title: 'ts_title' }, created() { axios.defaults.baseURL = ts_url ; var jsons = {}, qjson_data = {}; qjson_data['Permiss'] = 'test;zhao;Permi'; qjson_data['Fun'] = 'GetPermissListSign'; jsons['QJson'] = JSON.stringify(qjson_data); //Json转义 axios.post('/Server/Manage/AppManageClassFun', JSON.stringify(jsons), { headers: { 'Authorization': 'Basic VEhJTktTSUdOOjIwMTUxMTEz', 'Content-Type': 'application/json' } }) .then(res => { console.log(res.data) }) .catch(err => { console.error(err); }); }, }) </script>
大功告成