'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) { this.appId = 0; this.ak = ak; this.sk = sk; 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; return this.pms = this.devAuth.getToken().then(this.gotDevAuthSuccess.bind(this), this.gotDevAuthFail.bind(this)); } gotDevAuthSuccess(token) { // 如果用户没有手动调用setAccessToken设置access_token if (this.authType !== AUTHTYPE_DEV) { this.devAccessToken = token; this.authType = AUTHTYPE_DEV_OR_BCE; } this.status = STATUS_READY; return; } 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) { return this.pms.then(function() { let pms = this.preRequest(requestInfo); if (typeof pms == "undefined") { // 鉴权方式确定,请求接口 return httpClient.postWithInfo(requestInfo) } else { // 如果返回对象是promise,说明是需要重新获取access_token // 待重新获取完后继续请求接口 return pms.then(function() { this.preRequest(requestInfo); return httpClient.postWithInfo(requestInfo); }.bind(this)) } }.bind(this)) } preRequest(requestInfo) { // 如果前一次获取access_token服务发生错误,重新获取 if (this.status == STATUS_ERROR) { return this.authTypeReq(); } // 获取access_token失败,使用云方式调用 if (this.authType === AUTHTYPE_BCE) { requestInfo.makeBceOptions(this.ak, this.sk); return; } // 获取access_token成功,或者调用setAccessToken设置的access_token if (this.authType === AUTHTYPE_DEV_OR_BCE || this.authType === AUTHTYPE_DEV) { // 拥有AI平台接口权限 if (this.devAccessToken.hasScope(requestInfo.scope) || this.authType === AUTHTYPE_DEV) { // 判断access_token是否过期 if (!this.devAccessToken.isExpired()) { requestInfo.makeDevOptions(this.devAccessToken); return; } // access_token过期重新获取 return this.authTypeReq(); } else { // 使用云方式访问调用 requestInfo.makeBceOptions(this.ak, this.sk); } } } } module.exports = BaseClient;