'use strict';
|
/**
|
* Copyright (c) 2017 Baidu.com, Inc. All Rights Reserved
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
* the License. You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
* specific language governing permissions and limitations under the License.
|
*
|
* @file baseClient
|
* @author baiduAip
|
*/
|
const DevAuth = require('../auth/devAuth');
|
|
const DevAuthToken = require('../auth/devAuthToken');
|
|
|
/**
|
* 无授权判断状态
|
*
|
* @const
|
* @type {number}
|
*/
|
const AUTHTYPE_INIT = 0;
|
|
/**
|
* 确定为云用户
|
*
|
* @const
|
* @type {number}
|
*/
|
const AUTHTYPE_BCE = 1;
|
|
/**
|
* 确定为开发者用户(手动输入token模式,以及token中包含了正确的scope)
|
*
|
* @const
|
* @type {number}
|
*/
|
const AUTHTYPE_DEV = 2;
|
|
/**
|
* 获取开发者token成功用户
|
*
|
* @const
|
* @type {number}
|
*/
|
const AUTHTYPE_DEV_OR_BCE = 3;
|
|
|
/**
|
* 初始状态
|
*
|
* @const
|
* @type {number}
|
*/
|
const STATUS_INIT = 0;
|
|
/**
|
* 获取开发者token中
|
*
|
* @const
|
* @type {number}
|
*/
|
const STATUS_AUTHTYPE_REQESTING = 1;
|
|
/**
|
* 获取开发者token成功,或者确定为云用户
|
*
|
* @const
|
* @type {number}
|
*/
|
const STATUS_READY = 2;
|
|
/**
|
* 非法ak,sk
|
*
|
* @const
|
* @type {number}
|
*/
|
const STATUS_ERROR = -1;
|
|
/**
|
* BaseClient类
|
* 各具体接口类基类,处理鉴权逻辑等
|
*
|
* @constructor
|
* @param {string} appid appid.
|
* @param {string} ak The access key.
|
* @param {string} sk The security key.
|
*/
|
class BaseClient {
|
constructor(appId, ak, sk, options) {
|
this.appId = 0;
|
this.ak = ak;
|
this.sk = sk;
|
|
this.options = options || {};
|
|
this.authType = AUTHTYPE_INIT;
|
this.status = STATUS_INIT;
|
|
this.pms;
|
this.devAccessToken = null;
|
|
this.devAuth = new DevAuth(this.ak, this.sk);
|
|
this.authTypeReq();
|
|
}
|
setAccessToken(token, expireTime) {
|
let et = expireTime || DevAuthToken.DEFAULT_EXPIRE_DURATION;
|
this.devAccessToken = new DevAuthToken(token, et, null);
|
this.authType = AUTHTYPE_DEV;
|
this.status = STATUS_READY;
|
}
|
authTypeReq() {
|
// 请求access_token服务
|
this.status = STATUS_AUTHTYPE_REQESTING;
|
this.pms = this.devAuth.getToken().then(this.gotDevAuthSuccess.bind(this),
|
this.gotDevAuthFail.bind(this));
|
// 初始化client对象后立即发生的第一次异常,如果没有立即调用具体请求接口的话(必须有promise catch)
|
// 将无法被捕获获取token的request网络异常,为了避免UnhandledPromiseRejectionWarning
|
// 此处直接catch住,待代用具体接口时候再返回获取token时的异常,减少程序复杂度
|
this.pms.catch(function (error) {
|
}.bind(this));
|
return this.pms;
|
}
|
gotDevAuthSuccess(token) {
|
// 如果用户没有手动调用setAccessToken设置access_token
|
if (this.authType !== AUTHTYPE_DEV) {
|
this.devAccessToken = token;
|
this.authType = AUTHTYPE_DEV_OR_BCE;
|
}
|
this.status = STATUS_READY;
|
}
|
gotDevAuthFail(err) {
|
// 获取token时鉴权服务器返回失败信息
|
if (err.errorType === DevAuth.EVENT_ERRTYPE_NORMAL) {
|
// 可能是百度云的ak,sk
|
this.authType = AUTHTYPE_BCE;
|
this.status = STATUS_READY;
|
return;
|
}
|
|
// 获取token时发生了网络错误
|
// 或者是发生了服务器返回数据格式异常
|
if (err.errorType === DevAuth.EVENT_ERRTYPE_NETWORK
|
|| err.errorType === DevAuth.EVENT_ERRTYPE_ILLEGAL_RESPONSE) {
|
this.status = STATUS_ERROR;
|
throw err;
|
}
|
}
|
doRequest(requestInfo, httpClient) {
|
|
// 如果获取token失败
|
if (this.status === STATUS_ERROR) {
|
this.authTypeReq();
|
}
|
|
return this.pms.then(function () {
|
// 预检函数,返回是否token过期
|
let isTokenExpired = this.preRequest(requestInfo);
|
|
if (isTokenExpired === false) {
|
// 鉴权方式确定,请求接口
|
return httpClient.postWithInfo(requestInfo)
|
} else {
|
// 如果token过期了,说明是需要重新获取access_token
|
// 待重新获取完后继续请求接口
|
return this.pms.then(function () {
|
this.preRequest(requestInfo);
|
return httpClient.postWithInfo(requestInfo);
|
}.bind(this))
|
}
|
}.bind(this));
|
}
|
checkDevPermission(requestInfo) {
|
// 是否跳过这个检查(从speech.baidu.com创建的应用,调用语音接口需要跳过)
|
if (this.options.isSkipScopeCheck === true) {
|
return true;
|
}
|
// 检查是否拥有AI平台接口权限
|
return this.devAccessToken.hasScope(requestInfo.scope);
|
}
|
preRequest(requestInfo) {
|
|
// 获取access_token失败,使用百度云签名方式调用
|
if (this.authType === AUTHTYPE_BCE) {
|
requestInfo.makeBceOptions(this.ak, this.sk);
|
return false;
|
}
|
|
// 获取access_token成功,或者调用setAccessToken设置的access_token
|
if (this.authType === AUTHTYPE_DEV_OR_BCE || this.authType === AUTHTYPE_DEV) {
|
// 拥有AI平台接口权限
|
if (this.checkDevPermission(requestInfo) || this.authType === AUTHTYPE_DEV) {
|
|
// 判断access_token是否过期
|
if (!this.devAccessToken.isExpired()) {
|
requestInfo.makeDevOptions(this.devAccessToken);
|
return false;
|
}
|
// access_token过期重新获取
|
this.authTypeReq();
|
return true;
|
} else {
|
// 使用百度云签名方式访问调用
|
requestInfo.makeBceOptions(this.ak, this.sk);
|
}
|
}
|
return false;
|
}
|
}
|
|
module.exports = BaseClient;
|