import { SDKAdapterInterface , AbstractSDKRequest , IRequestOptions , ResponseObject , IUploadRequestOptions , IRequestConfig , IRequestMethod } from '@cloudbase/adapter-interface' ; import { protocol } from '../../types' ; import { isFormData , formatUrl , toQueryString } from '../../lib/util' ; class class WebRequest extends AbstractSDKRequest { private readonly _timeout : number ; private readonly _timeoutMsg : string ; private readonly _restrictedMethods : Array < IRequestMethod > ; constructor ( config ) { super ( ) ; const { timeout , timeoutMsg , restrictedMethods } = config ; this . _timeout = timeout || 0 ; this . _timeoutMsg = timeoutMsg || '请求超时' ; this . _restrictedMethods = restrictedMethods || [ 'get' , 'post' , 'upload' , 'download' ] ; } public get ( options ) { return this . _request ( { ... options , method : 'get' } , this . _restrictedMethods . includes ( 'get' ) ) ; } public post ( options ) { return this . _request ( { ... options , method : 'post' } , this . _restrictedMethods . includes ( 'post' ) ) ; } public put ( options ) { return this . _request ( { ... options , method : 'put' } ) ; } public upload ( options ) { const { data , file , name } = options ; const formData = new FormData ( ) ; for ( const key in data ) { formData . append ( key , data [ key ] ) ; } formData . append ( 'key' , name ) ; formData . append ( 'file' , file ) ; return this . _request ( { ... options , data : formData , method : 'post' } , this . _restrictedMethods . includes ( 'upload' ) ) ; } public async download ( options ) { try { const { data } = await this . get ( { ... options , headers : { } , responseType : 'blob' } ) ; const url = window . URL . createObjectURL ( new Blob ( [ data ] ) ) ; const fileName = decodeURIComponent ( new URL ( options . url ) . pathname . split ( '/' ) . pop ( ) || '' ) ; const link = document . createElement ( 'a' ) ; link . href = url ; link . setAttribute ( 'download' , fileName ) ; link . style . display = 'none' ; document . body . appendChild ( link ) ; link . click ( ) ; window . URL . revokeObjectURL ( url ) ; document . body . removeChild ( link ) ; } catch ( e ) { } return new Promise ( resolve => { resolve ( { statusCode : 200 , tempFilePath : options . url } ) ; } ) ; } param { IRequestOptions } options param { boolean } enableAbort protected _request ( options , enableAbort = false ) { const method = ( String ( options . method ) ) . toLowerCase ( ) || 'get' ; return new Promise ( resolve => { const { url , headers = { } , data , responseType , withCredentials , body , onUploadProgress } = options ; const realUrl = formatUrl ( protocol , url , method === 'get' ? data : { } ) ; const ajax = new XMLHttpRequest ( ) ; ajax . open ( method , realUrl ) ; responseType && ( ajax . responseType = responseType ) ; for ( const key in headers ) { ajax . setRequestHeader ( key , headers [ key ] ) ; } let timer ; if ( onUploadProgress ) { ajax . addEventListener ( 'progress' , onUploadProgress ) ; } ajax . onreadystatechange = ( ) => { const result = { } ; if ( ajax . readyState === 4 ) { let headers = ajax . getAllResponseHeaders ( ) ; let arr = headers . trim ( ) . split ( /[\r\n]+/ ) ; let headerMap = { } ; arr . forEach ( function ( line ) { let parts = line . split ( ': ' ) ; let header = parts . shift ( ) . toLowerCase ( ) ; let value = parts . join ( ': ' ) ; headerMap [ header ] = value ; } ) ; result . header = headerMap ; result . statusCode = ajax . status ; try { result . data = responseType === 'blob' ? ajax . response : JSON . parse ( ajax . responseText ) ; } catch ( e ) { result . data = responseType === 'blob' ? ajax . response : ajax . responseText ; } clearTimeout ( timer ) ; resolve ( result ) ; } } ; if ( enableAbort && this . _timeout ) { timer = setTimeout ( ( ) => { console . warn ( this . _timeoutMsg ) ; ajax . abort ( ) ; } , this . _timeout ) ; } let payload ; if ( isFormData ( data ) ) { payload = data ; } else if ( headers [ 'content-type' ] === 'application/x-www-form-urlencoded' ) { payload = toQueryString ( data ) ; } else if ( body ) { payload = body ; } else { payload = data ? JSON . stringify ( data ) : undefined ; } if ( withCredentials ) { ajax . withCredentials = true ; } ajax . send ( payload ) ; } ) ; } } function genAdapter ( ) { const adapter = { root : window , reqClass : WebRequest , wsClass : WebSocket , localStorage : localStorage , sessionStorage : sessionStorage } ; return adapter ; } export { genAdapter , WebRequest } ;