koa 处理axios请求_koa解决 vue axios请求允许请求发送token - CSDN
精华内容
参与话题
  • axios里如何优雅的处理网络超时

    千次阅读 2019-09-20 12:05:02
    在前端项目中,我们一般通过axios的拦截器对后端的请求和响应进行统一处理。 网络超时属于返回异常的一种。因此我们需要在拦截器的response中对error进行处理: 我们首先设置axios的正常请求的timeouot为4000ms,...

    网络超时的常见表现就是我们请求一个接口如果长时间得不到服务器的响应。就会出现网络中断,报错提示网络超时。

    在前端项目中,我们一般通过axios的拦截器对后端的请求和响应进行统一处理。

    网络超时属于返回异常的一种。因此我们需要在拦截器的response中对error进行处理:

    我们首先设置axios的正常请求的timeouot为4000ms,也就是4秒钟如果得不到服务器响应就会中断。

    第二步:我们给后端接口设置一个大于4秒的延迟,比如10秒。也就是说10秒以后,财返回数据给前端。

    本例中我们利用koa2作为服务器:

    接下来我们看看axios拦截器的response里error到底是啥?

    在控制台我们会发现:

    这个error其实下面有属性:message:错误的文本信息,code。错误码:

    经打印发现:

    error.code='ECONNABORTED',

    error.message='Network Error'

    因此我们可以通过判断这两个属性得知道=是否超时,然后做出提示:

     

     

     

    展开全文
  • 我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器...

    我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们只需要请求后端服务器的接口即可实现系统的业务功能开发.这个过程中会涉及到web页面API服务器的跨域访问(由于受到浏览器的同源策略,但是业界已有很多解决方案,接下来会介绍).通过这种开发模式使得我们真正的实现了前后端完全分离.

    采用这种前后端单独开发部署的模式好处有如下几点:

    • 减少后端服务器的并发/负载压力

    • 前端项目和后端项目完全分离, 一定程度上提高了自动化部署的灵活性, 并且代码更易管理和维护

    • 提高前后端开发团队的工作效率, 各司其职, 出现bug更容易定位问题

    • 在大并发情况下可以同水平扩展前后端服务器,利用多台前端服务器做集群来抗住日均千万级的pv

    • 提高应用容错, 即使是API服务器挂了, 前端页面依然能正常访问

    • API服务器能同时为多个应用平台提供服务, 大量复用接口,提升效率。(比如说微服务)

    虽然好处有很多, 但是为了实现以上的架构模式, 我们首先要解决的就是跨域问题.

    浏览器的同源策略

    同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

    如果两个URL的protocol(协议,比如http协议,https协议)、port (端口号,如80)和 host(主机,如developer.mozilla.org) 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。也就是说如果不满足以上3个条件中的任意一个,则被视为跨域.

    解决跨域问题的几种方式

    业界解决浏跨域问题的方案很多, 笔者在这里粗略介绍一下:

    • JSONP实现跨域 通过script标签和url回调来实现跨域, 缺点是只支持get请求

    • CORS CORS需要浏览器和后端同时支持, 后端设置Access-Control-Allow-Origin 就可以开启 CORS

    • postMessage 可以实现跨文本档、多窗口、跨域消息传递(笔者之前写可插拔式聊天机器人就是采用该方案)

    • websocket websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,也是跨域的一种解决方案

    • nginx反向代理

    • document.domain + iframe 比较传统的跨域解决方案

    目前作为大规模跨域开发使用最多的模式还是CORS方案,所以笔者接下来将具体介绍采用cors模式搭建前后端跨域访问通用解决方案, 为了方便,笔者后端将采用nodejs+koa, (java/php开发类似), 前端采用axios作为请求库来配合实现完整的cors模式.

    跨域开发的后端配置(node/koa版)

    要想彻底了解cors的跨域模式, 我们还是要深入实践中来, 笔者将采用nodejskoa中间件来实现cors模式的搭建.这里笔者先简单介绍一下cors:

    跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头 来告诉浏览器 让运行在一个域上的Web应用被准许访问来自不同源服务器上指定的资源。

    基本场景如下:

    对于简单的跨域场景,我们只需要设置请求头的Access-Control-Allow-Origin字段即可, 比如设置为*号表示允许任何域名的访问.

    这里我们使用koa2-cors这个中间件来实现一下, 代码如下:

    import koa from 'koa';
    import cors from 'koa2-cors';
    const app = new koa();
    // 设置跨域
    app.use(cors({
        origin: function (ctx) {
            return '*'
        }
    }))
    
    复制代码
    

    通过这样的配置, 我们就能轻松实现cors跨域, 不过现实开发中我们一般不会这么设置, 因为这样设置意味着任何人都能访问我们的服务,安全性无法保证. 作为小型的开放服务,可以采用这样的配置加上访问限流来实现免费图床类应用.(开放图床实现可以参考笔者之前写的文章使用nodeJs开发自己的图床应用)

    在实际开发中, 我们会将origin的返回值设置为指定域名, 这样就只允许该域名下的请求访问, 所以正确的姿势如下:

    import koa from 'koa';
    import cors from 'koa2-cors';
    const app = new koa();
    const isDev = process.env.NODE_ENV === 'development';
    // 设置跨域
    app.use(cors({
        origin: function (ctx) {
            return isDev ? '*' : 'http://qutanqianduan.com'
        }
    }))
    
    复制代码
    

    通过这种方式, 我们在开发环境中, 可以让前端同事自由访问我们的API接口, 提高联调效率, 而在生产环境中只允许我们的WEB服务器所在域名访问.

    更进一步

    对于简单请求和简单的开发模式, 以上的设计就基本满足要求了, 但是对于复杂的业务场景, 我们的请求模式往往会涉及到更多的要求, 比如说需要携带cookie, 用户凭证或者自定义的请求头信息等(比如典型的JWT认证的token一般会存放到自定义的头信息中), 此时往往会发送预检请求(要求必须先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响).

    这里我们需要了解以下几个响应头部的字段:

    • Access-Control-Allow-Methods 表明服务器允许客户端使用的请求方法

    • Access-Control-Allow-Headers 表明服务器允许请求中携带的头部字段

    • Access-Control-Max-Age 表明响应的有效时间。在有效时间内,浏览器无须为同一请求再次发起预检请求

    • Access-Control-Expose-Headers 服务器允许浏览器访问的头信息白名单

    • Access-Control-Allow-Credentials 指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容

    以上这5个响应头部字段非常重要,这也是我们解决复杂跨域场景的关键配置. 具体配置案例如下:

    // 设置跨域
    app.use(cors({
        origin: function (ctx) {
            if (ctx.url.indexOf(config.API_VERSION_PATH) > -1) {
              return isDev ? 'http://192.xxx.1.3:8000' : 'http://qutanqianduan.cn'; // 允许来自指定域名请求, 如果设置为*,前端将获取不到错误的响应头
            }
        },
        exposeHeaders: ['WWW-Authenticate', 'Server-Authorization', 'x-show-msg'],
        maxAge: 5,  //  该字段可选,用来指定本次预检请求的有效期,单位为秒
        credentials: true,  // 允许携带用户凭证
        allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // 允许的请求方法
        allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Requested-With'] // 允许接收的头部字段
    }))
    
    复制代码
    

    以上是采用koa2-cors实现的方案, 通过设置exposeHeaders, 我们就可以在浏览器端拿到服务器响应的头部字段'WWW-Authenticate', 'Server-Authorization', 'x-show-msg', 进而根据这些字段的值来实现定制化的消息机制.

    需要注意的是, 我们服务器在设置credentials后,需要前端请求库配置设置,比如我们需要在axios中设置withCredentials为true, 代码如下:

    import axios from 'axios'
    const isDev = process.env.NODE_ENV === 'development'
    const instance = axios.create({
        baseURL: isDev ? 'http://localhost:3000/api/xxx' : 'http://localhost/api/xxx',
        withCredentials: true
    });
    
    复制代码
    

    这样我们就能成功携带用户凭证并被跨域的后端服务器获取了.以上就实现了我们cors模式的后端配置, 对于nodeJS为主的后端选手, 基本任务已经完成, 对于java/PHP选手, 也可以参考类似的配置和库来实现. 接下来我们来实现前端请求库的封装.

    跨域开发的前端请求库封装(axios版)

    作为一名前端工程师, 没有一个上手的请求库是万万不行的, 目前业界比较好的轮子有axiosumi-request等, 但是后者在使用过程中有一些坑(毕竟基于fetch实现), 所以这里笔者将基于axios来简单实现一个跨域请求库的封装.方便大家集成在自己的vue或者react项目中. 接下来看看请求库封装的简单模型:

    笔者将基于http规范的错误类型进行基本的消息系统设计, 代码如下:

    import axios from 'axios'
    import { message } from 'antd'
    
    const isDev = process.env.NODE_ENV === 'development'
    
    const instance = axios.create({
        baseURL: isDev ? 'http://localhost:3000/api/xxx' : 'http://qutanqianduan/api/xxx',
        timeout: 10000,
        withCredentials: true
    });
    
    // 添加请求拦截器
    instance.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        config.headers = {
            'x-requested-with': localStorage.getItem('user') || '',
            'authorization': localStorage.getItem('token') || ''
        }
        return config;
      }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      });
    
    // 添加响应拦截器
    instance.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        if(response.headers['x-show-msg'] === 'zxzk_msg_200') {
            message.success(response.data.msg);
        }
        return response.data.result;
      }, function (error) {
        // 对响应错误做点什么
        const { response } = error;
        if(response.status === 404) {
            message.error('请求资源未发现');
        }else if(response.status === 403) {
            message.error(response.data.msg, () => {
                window.location.href = '/login'
            });
        }else {
            message.error(response.data.msg);
        }
        return Promise.reject(error);
      });
    
    export default instance
    
    复制代码
    

    以上笔者结合antd的message作为消息反馈UI,利用axios的请求和响应拦截来实现消息系统的设计, 以上只是基本的框架, 大家可以基于以上设计进行更加自定义的封装.

    讲到这里, 大家是不是对跨域下的服务端和前端配置有了更进一步的了解了呢?

    最后

    如果想学习更多H5游戏webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

    更多推荐

    轻松使用纯css3打造有点意思的故障艺术(附React加强组件版)

    快速在你的vue/react应用中实现ssr(服务端渲染)

    当后端一次性丢给你10万条数据, 作为前端工程师的你,要怎么处理?

    展开全文
  • koa2的作用和express都差不多,都是在common.js环境下运行 都是用来构建服务器 koa2 npm init // 初始化 npm install koa2 --save // 安装koa2框架 npm install koa-router --save // 安装koa2中间件 axios...

    koa2的作用和express都差不多,都是在common.js环境下运行
    都是用来构建服务器

    koa2

    npm init // 初始化
    npm install koa2 --save  // 安装koa2框架
    npm install koa-router --save // 安装koa2中间件	
    

    axios(和ajax作用一样)

    npm install axios --save // 安装axios
    <script src="./node_modules/axios/dist/axios.js"></script> 
    // 下载下来只会由于现阶段用的都是script引入js,不是webpack不能通过import引用模块
    

    server.js (创建服务的js文件)

    是基于promise对象的技术

    const Koa = require('koa2'); // 加载koa2模块
    let app = new Koa(); // 实例化
    const Router = require('koa-router');
    const router = new Router();
    router.get('/',async ctx => { // 设置路由  ctx是request和reponse的结合
      ctx.body = { // 响应到页面中的数据 ctx.body代表报文的主体
        token:'abc', // 通过axios会直接把body中的内容返回
        msg:'ok'
      };
    })
    app.use( router.routes() ); //把router对象的routes挂载到app上不然找不到,使用这个中间件
    app.listen(9999,() => { // 对服务的监听
    	console.log("服务启动成功端口号为9999")
    })
    

    前台用来获取数据的页面,这个页面没有必要必须挂载到服务器上

    var App = {
    			template:`
    				<div>
    					<button @click = 'sendAjax'>发请求</button>
    				</div>
    			`,
    			methods:{
    				sendAjax(){
    					this.$axios.get('http://127.0.0.1:9999/') // 对本地的服务器发出请求
    					.then(res=>{
    						console.log(res);
    					})
    					.catch(err=>{
    						console.log(err);
    					})
    				}
    			}
    		};
    		Vue.prototype.$axios = axios // 将axios.js暴露出的axios对象给Vue的原型主要就可以在vue中直接使用了
    			new Vue({
    			el:'#app',
    			template:`<App />`,
    			components:{
    				App
    			}
    		});
    

    在这里插入图片描述
    返回的req和res集合的对象data是ctx.body中的数据
    axios是一种基于promise的技术

    router.post('/upload',async (ctx,next)=>{
      console.log('上传成功')
      ctx.body = 'ok';
    })
    .post('/add',async ctx => {
      ctx.req.on('data',data=>{
          console.log(data);  // <Buffer 61 3d 31>
          console.log(data.toString()); // a = 1
      });
      ctx.body = 'post ok';
    });
    
    

    前端的js

    var App = {
    			data(){
    				return {
    					res1:"",
    					res2:''
    				}
    			},
    			template:`
    				<div>
    					响应1:{{res1}}
    					响应2:{{res2}}
    					<button @click = 'sendAjax'>合并强求</button>
    				</div>
    			`,
    			methods:{
    				sendAjax(){
    					// 请求1 get:  /
    					// 请求 post : /add
    					this.$axios.defaults.baseURL = 'http://127.0.0.1:8888';
    					// 设置请求的默认路径
    					var q1 = this.$axios.get('/'); // 请求 / 
    					var q2 = this.$axios.post('/add','a=1'); // 请求 /add
    					this.$axios.all([q1,q2]) // 同时发出请求 解决高并发的问题
    					.then(this.$axios.spread((res1,res2)=>{ // 请求结束后获取对应的报表对象
    					// all会等待最后一个执行结束后开始返回内容
    						// 全部成功了
    						this.res1 = res1.data;
    						this.res2 = res2.data;
    					}))
    					.catch(err=>{
    						// 其一失败
    						console.log(err);
    					})
    				}
    			}
    		};
    		Vue.prototype.$axios = axios
    		new Vue({
    			el:'#app',
    			template:`<App />`,
    			components:{
    				App
    			}
    		});
    

    事件触发后
    在这里插入图片描述

    transformResponse和 transformRequest

    用来在请求前和请求后对提交和获取的数据进行处理
    可以通过修改data的内容来改变获取或提交的内容

    // 公用上面我创建的服务
     var App = {
            template: `
    				<div>
    					<button @click = 'sendAjax'>发请求</button>
    				</div>
    			`,
            methods: {
                sendAjax() {
    
                    this.$axios.defaults.baseURL = 'http://127.0.0.1:8888/'
                    this.$axios.get('', {
                            params: { id: 1 }, // 和要请求发出的数据在一个对象中
                            // 在传递给then/catch之前,允许修改响应的数据
                            transformResponse: [function(data) {
                                // 对 data 进行任意转换处理
                                // 会将data转化为json类型的数据方便出来
                                console.log(data); // string类型的{"token":"abc","msg":"ok"}
                                console.log(typeof data); // string 我测试的时候是只要使用transformResponsedata传来的就是string类型的
                                data = JSON.parse(data); // 对获取的data进行出来
                                console.log(data); // 假如我在这里给data重新赋一个值他的下面res接受到的内容就会发生变化
                                return data; // 如果中间什么都不写 会返回undefinded
                            }]
                        })
                        .then(res => {
                            console.log(res.data.msg); // ok
                        })
                        .catch(err => {
                            console.log(err);
                        })
                    this.$axios.post('/add', {
                            firstName: 'Fred' 
                            // 这是我要提交到后台的数据
                        }, {
                            // `transformRequest` 允许在向服务器发送前,修改请求数据
                            // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
                            // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
                            transformRequest: [function(data) {
                                // 对 data 进行任意转换处理 这里不会转化为json类型
                                console.log(data); //对象类型的{firstName: "Fred"}
                                return data; // 如果我改变data的话提交的内容会发生变化
                            }],
    
                        })
                        .then(res => {
                            console.log(res);
                        })
                        .catch(err => {
                            console.log(err);
                        })
                }
            }
    
        };
        Vue.prototype.$axios = axios
        new Vue({
            el: '#app',
            template: `<App />`,
            components: {
                App
            }
        });
    
    展开全文
  • 使用axios发送前端post请求到后端,url为后端服务器地址 axios({ method: 'post', url: 'http://localhost:3000/login', data: { name: this.user.username, email: this.user.email, password: this.user....

    前端

    使用axios发送前端post请求到后端,url为后端服务器地址

    axios({
              method: 'post',
              url: 'http://localhost:3000/login',
              data: { name: this.user.username,
                email: this.user.email,
                password: this.user.password
              }
            })
              .then(res => {
                console.log(this.data)
                console.log(res)
                if (res.data.status === 200) {
                } else {
                  alert('您输入的用户名已存在!')
                }
              })
    

    由于后端端口号3000,受同源策略影响,须在后端进行cors插件的设置,这里采用koa2-cors

    const cors = require('koa2-cors')
    

    使用中间件进行一些基本的配置

    app.use(cors({
      origin: function (ctx) {
        if (ctx.url === '/test') {
          return '*' // 允许来自所有域名请求
        }
        return 'http://localhost:8080'
      },
      exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
      maxAge: 5,
      credentials: true,
      allowMethods: ['GET', 'POST', 'DELETE'],
      allowHeaders: ['Content-Type', 'Authorization', 'Accept']
    }))
    

    后端使用post路由接收即可,注意将对象转换为json数据

    router.post('/login', koaBody(), async (ctx) => {
      console.log(ctx.request.body)
      let user = JSON.stringify(ctx.request.body)
      console.log(user)
    })
    

    这里在项目中遇见一个巨坑,因为前端请求方式是application/jsonkoa-bodyparser插件不识别!!!
    所以一定要改用koa-body插件代替,且把body-parser注释掉,防止不必要的麻烦

    // const bodyParser = require('koa-bodyparser')
    const koaBody = require('koa-body')
    

    在路由中koaBody()即可使用

    router.post('/login', koaBody(), async (ctx) => {
    })
    

    这样,一个简单的前后端交互就完成啦,放心玩耍吧

    展开全文
  • 我的博客的服务端是采用的koa2 + MySQL,后台管理界面采用的是:Vue+ElementUi+axios。这都是些常规组合,没有什么好说的。 二、服务端 ==koa2-cors:== 用来是设置跨域请求; // 官方推荐配置 var Koa = ...
  • Nodejs——axios请求接口及拦截器使用

    千次阅读 2019-09-30 15:43:53
    一、关于axios的使用 安装依赖:npm install --save axios api 可以参考https://www.npmjs.com/package/axios 以下针对https://blog.csdn.net/wx19900503/article/details/101775442文中的接口服务,写了几种请求...
  • 1、安装axios npm install axios --save -g 2、先写好拦截器、服务等 新建一个名为http_server.js的文件 // http_server.js var axios = require("axios") // 创建axios实例s const service = axios....
  • 前面讲了环境的搭建用webpack打包vue,Vue-router,...下面讲一下使用nodejs+koa提供接口,axios访问接口,前后端数据通信的相关内容。 11.使用nodejs+koa2提供后台接口 npm install koa koa-router --save-dev 在根目...
  • 前端vue let param = new FormData(); //创建form对象 param.append('img',state.banner.edi.pic);//图片文件 param.append('sort',state.banner.edi.sort);//正常内容 let config = { headers:{'Content-Type'...
  • 废话不多说,看图: 注意:是反括号,不是普通的单引号
  • vue的axios请求,获取到的服务端session为空 验证码保存在session中,但是存在跨域请求,session不一致问题(这个问题困扰了一天) 起因:http是无状态的,因此我们通常需要用到cookie以及session来保存状态,...
  • koa-body可以处理三种类型的请求 multipart/form-data application/x-www-urlencoded application/json const Koa = require('koa') const app = new Koa() const koaBody = require('koa-...
  • 环境 node: v12.16.1 ...const koa = require('koa'); const koaBody = require('koa-body'); const fs = require('fs'); const ExcelJS = require('exceljs') const APP = new koa(); APP.use(k
  • CORS跨域设置 CORS(Cross-originresourcesharing),跨域资源共享,是一份浏览器...options是浏览器默认行为,表示的是非简单请求,会请求两次 写在app use里可以成为公用,不用每个router都添加cors 1.('Acc...
  • axiosaxios拦截器axios取消发送请求基本流程实例演示 axios拦截器 拦截器是什么? 以我的理解,拦截器就是一个回调函数,里面包含了一些逻辑处理的代码,它分为请求拦截器,其在请求发送之前执行,处理一些请求发送...
  • &lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport"...
  • axios.post请求获取404

    2019-12-23 17:06:31
    <p>Client side(React/axios.post) failed to post to server side api (Golang/gin) with status code 404. I want to make this post request success. <p>Following curl success to write data in mysql table ...
  • 最近在使用vue axios发送请求,结果出现跨域问题,网上查了好多,发现有好几种结局方案。 1:服务器端设置跨域 header(“Access-Control-Allow-Origin:*”); header(“Access-Control-Allow-Headers:content-type...
  • axios携带cookie配置详解(axios+koa)

    万次阅读 2019-01-14 14:02:21
    axios.defaults.withCredentials = true; //配置为true axios.post('http://localhost:3000/tpzdz/vote/all', { openid: 'oJ0mVw4QrfS603gFa_uAFDADH2Uc', date: '2018-11-21' }).then(functio...
  • ajax问题 浏览器同源策略 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源 源:协议、域名和端口号 跨域 不受同源策略影响的资源的引入 ...link&...
1 2 3 4 5 ... 20
收藏数 1,070
精华内容 428
关键字:

koa 处理axios请求