@@ -7,6 +7,7 @@ const request = require('superagent');
77const debug = require ( 'debug' ) ( 'request' ) ;
88const md5 = require ( 'md5' ) ;
99const Promise = require ( './promise' ) ;
10+ const Cache = require ( './cache' ) ;
1011
1112// 计算 X-LC-Sign 的签名方法
1213const sign = ( key , isMasterKey ) => {
@@ -87,7 +88,6 @@ const ajax = (method, resourceUrl, data, headers = {}, onprogress) => {
8788} ;
8889
8990const setHeaders = ( AV , sessionToken ) => {
90-
9191 const headers = {
9292 'X-LC-Id' : AV . applicationId ,
9393 'Content-Type' : 'application/json;charset=UTF-8' ,
@@ -137,7 +137,7 @@ const createApiUrl = (AV, route, className, objectId, method, dataObject) => {
137137 let apiURL = AV . _config . APIServerURL ;
138138
139139 // Test Data
140- // apiURL = 'https://e1-api.leancloud.cn';
140+ apiURL = 'https://e1-api.leancloud.cn' ;
141141
142142 if ( apiURL . charAt ( apiURL . length - 1 ) !== '/' ) {
143143 apiURL += '/' ;
@@ -176,14 +176,78 @@ const createApiUrl = (AV, route, className, objectId, method, dataObject) => {
176176 return apiURL ;
177177} ;
178178
179- /**
180- When API request need to redirect to the right location,
181- can't use browser redirect by http status 307, as the reason of CORS,
182- so API server response http status 410 and the param "location" for this case.
183- */
184- // const retryRequest = () => {
179+ const cacheServerURL = ( serverURL , ttl ) => {
180+ if ( typeof ttl !== 'number' ) {
181+ ttl = 3600 ;
182+ }
183+ Cache . set ( 'APIServerURL' , serverURL , ttl * 1000 ) ;
184+ } ;
185+
186+ // handle AV._request Error
187+ const handleError = ( AV , res ) => {
188+ const promise = new Promise ( ) ;
189+ /**
190+ When API request need to redirect to the right location,
191+ can't use browser redirect by http status 307, as the reason of CORS,
192+ so API server response http status 410 and the param "location" for this case.
193+ */
194+ if ( res . statusCode === 410 ) {
195+
196+ } else {
197+ let errorJSON = { code : - 1 , error : res . responseText } ;
198+ if ( res . response && res . response . code ) {
199+ errorJSON = res . response ;
200+ } else if ( res . responseText ) {
201+ try {
202+ errorJSON = JSON . parse ( res . responseText ) ;
203+ } catch ( e ) {
204+ // If we fail to parse the error text, that's okay.
205+ }
206+ }
207+
208+ // Transform the error into an instance of AV.Error by trying to parse
209+ // the error string as JSON.
210+ const error = AV . Error ( errorJSON . code , errorJSON . error ) ;
211+ promise . reject ( error ) ;
212+ }
213+ return promise ;
214+ } ;
185215
186- // };
216+ const setRegionServer = ( AV , region = 'cn' ) => {
217+ // 服务器请求的节点 host
218+ const API_HOST = {
219+ cn : 'https://api.leancloud.cn' ,
220+ us : 'https://us-api.leancloud.cn' ,
221+ } ;
222+
223+ const AVConfig = AV . _config ;
224+ AVConfig . region = region ;
225+ // 如果用户在 init 之前设置了 APIServerURL,则跳过请求 router
226+ if ( AVConfig . APIServerURL ) {
227+ return ;
228+ }
229+ AVConfig . APIServerURL = API_HOST [ region ] ;
230+ if ( region === 'cn' ) {
231+ Cache . get ( 'APIServerURL' ) . then ( cachedServerURL => {
232+ if ( cachedServerURL ) {
233+ return cachedServerURL ;
234+ } else {
235+ return ajax ( 'get' , `https://app-router.leancloud.cn/1/route?appId=${ AV . applicationId } ` )
236+ . then ( servers => {
237+ if ( servers . api_server ) {
238+ cacheServerURL ( servers . api_server , servers . ttl ) ;
239+ return servers . api_server ;
240+ }
241+ } ) ;
242+ }
243+ } ) . then ( serverURL => {
244+ // 如果用户在 init 之后设置了 APIServerURL,保持用户设置
245+ if ( AVConfig . APIServerURL === API_HOST [ region ] ) {
246+ AVConfig . APIServerURL = `https://${ serverURL } ` ;
247+ }
248+ } ) ;
249+ }
250+ } ;
187251
188252const init = ( AV ) => {
189253 /**
@@ -207,35 +271,15 @@ const init = (AV) => {
207271
208272 return setHeaders ( AV , sessionToken ) . then (
209273 headers => ajax ( method , apiURL , dataObject , headers )
210- . then ( null , ( response ) => {
211- // Transform the error into an instance of AV.Error by trying to parse
212- // the error string as JSON.
213- let error ;
214- if ( response ) {
215- if ( response . response ) {
216- error = new AV . Error ( response . response . code , response . response . error ) ;
217- } else if ( response . responseText ) {
218- try {
219- const errorJSON = JSON . parse ( response . responseText ) ;
220- if ( errorJSON ) {
221- error = new AV . Error ( errorJSON . code , errorJSON . error ) ;
222- }
223- } catch ( e ) {
224- // If we fail to parse the error text, that's okay.
225- }
226- }
227- }
228- error = error || new AV . Error ( - 1 , response . responseText ) ;
229-
230- // By explicitly returning a rejected Promise, this will work with
231- // either jQuery or Promises/A semantics.
232- return Promise . error ( error ) ;
233- } )
274+ . then ( null , ( res ) =>
275+ handleError ( AV , res )
276+ )
234277 ) ;
235278 } ;
236279} ;
237280
238281module . exports = {
239282 init,
240283 ajax,
284+ setRegionServer,
241285} ;
0 commit comments