123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import RNFetchBlob from '../index.js'
- import Log from '../utils/log.js'
- import fs from '../fs'
- import unicode from '../utils/unicode'
- import Blob from './Blob'
-
- const log = new Log('FetchPolyfill')
-
- log.disable()
- // log.level(3)
-
- export default class Fetch {
-
- constructor(config:RNFetchBlobConfig) {
- Object.assign(this, new RNFetchBlobFetchPolyfill(config))
- }
-
- }
-
- class RNFetchBlobFetchPolyfill {
-
- constructor(config:RNFetchBlobConfig) {
- this.build = () => (url, options = {}) => {
-
- let body = options.body
- let promise = Promise.resolve()
- let blobCache = null
-
- options.headers = options.headers || {}
- let ctype = options['Content-Type'] || options['content-type']
- let ctypeH = options.headers['Content-Type'] || options.headers['content-type']
- options.headers['Content-Type'] = ctype || ctypeH
- options.headers['content-type'] = ctype || ctypeH
- options.method = options.method || 'GET'
- if(body) {
- // When the request body is an instance of FormData, create a Blob cache
- // to upload the body.
- if(body instanceof FormData) {
- log.verbose('convert FormData to blob body')
- promise = Blob.build(body).then((b) => {
- blobCache = b
- options.headers['Content-Type'] = 'multipart/form-data;boundary=' + b.multipartBoundary
- return Promise.resolve(RNFetchBlob.wrap(b._ref))
- })
- }
- // When request body is a Blob, use file URI of the Blob as request body.
- else if (body.isRNFetchBlobPolyfill)
- promise = Promise.resolve(RNFetchBlob.wrap(body.blobPath))
- else if (typeof body !== 'object' && options.headers['Content-Type'] !== 'application/json')
- promise = Promise.resolve(JSON.stringify(body))
- else if (typeof body !== 'string')
- promise = Promise.resolve(body.toString())
- // send it as-is, leave the native module decide how to send the body.
- else
- promise = Promise.resolve(body)
- }
- // task is a progress reportable and cancellable Promise, however,
- // task.then is not, so we have to extend task.then with progress and
- // cancel function
- let progressHandler, uploadHandler, cancelHandler
- let statefulPromise = promise
- .then((body) => {
- let task = RNFetchBlob.config(config)
- .fetch(options.method, url, options.headers, body)
- if(progressHandler)
- task.progress(progressHandler)
- if(uploadHandler)
- task.uploadProgress(uploadHandler)
- if(cancelHandler)
- task.cancel()
- return task.then((resp) => {
- log.verbose('response', resp)
- // release blob cache created when sending request
- if(blobCache !== null && blobCache instanceof Blob)
- blobCache.close()
- return Promise.resolve(new RNFetchBlobFetchResponse(resp))
- })
- })
-
- // extend task.then progress with report and cancelling functions
- statefulPromise.progress = (fn) => {
- progressHandler = fn
- }
- statefulPromise.uploadProgress = (fn) => {
- uploadHandler = fn
- }
- statefulPromise.cancel = () => {
- cancelHandler = true
- if(task.cancel)
- task.cancel()
- }
-
- return statefulPromise
-
- }
- }
-
- }
-
- class RNFetchBlobFetchResponse {
-
- constructor(resp:FetchBlobResponse) {
- let info = resp.info()
- this.headers = info.headers
- this.ok = info.status >= 200 && info.status <= 299,
- this.status = info.status
- this.type = 'basic'
- this.bodyUsed = false
- this.resp = resp
- this.rnfbRespInfo = info
- this.rnfbResp = resp
- }
-
- rawResp() {
- return Promise.resolve(this.rnfbResp)
- }
-
- arrayBuffer(){
- log.verbose('to arrayBuffer', this.rnfbRespInfo)
- this.bodyUsed = true
- return readArrayBuffer(this.rnfbResp, this.rnfbRespInfo)
- }
-
- text() {
- log.verbose('to text', this.rnfbResp, this.rnfbRespInfo)
- this.bodyUsed = true
- return readText(this.rnfbResp, this.rnfbRespInfo)
- }
-
- json() {
- log.verbose('to json', this.rnfbResp, this.rnfbRespInfo)
- this.bodyUsed = true
- return readJSON(this.rnfbResp, this.rnfbRespInfo)
- }
-
- blob() {
- log.verbose('to blob', this.rnfbResp, this.rnfbRespInfo)
- this.bodyUsed = true
- return readBlob(this.rnfbResp, this.rnfbRespInfo)
- }
- }
-
- /**
- * Get response data as array.
- * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
- * @param {RNFetchBlobResponseInfo} info Response informations.
- * @return {Promise<Array>}
- */
- function readArrayBuffer(resp, info):Promise<Array> {
- switch (info.rnfbEncode) {
- case 'path':
- return resp.readFile('ascii')
- break
- default:
- let buffer = []
- let str = resp.text()
- for (let i in str) {
- buffer[i] = str.charCodeAt(i);
- }
- return Promise.resolve(buffer)
- break
- }
- }
-
- /**
- * Get response data as string.
- * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
- * @param {RNFetchBlobResponseInfo} info Response informations.
- * @return {Promise<string>}
- */
- function readText(resp, info):Promise<string> {
- switch (info.rnfbEncode) {
- case 'base64':
- return Promise.resolve(resp.text())
- break
- case 'path':
- return resp.text()
- break
- default:
- return Promise.resolve(resp.text())
- break
- }
- }
-
-
- /**
- * Get response data as RNFetchBlob Blob polyfill object.
- * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
- * @param {RNFetchBlobResponseInfo} info Response informations.
- * @return {Promise<Blob>}
- */
- function readBlob(resp, info):Promise<Blob> {
- log.verbose('readBlob', resp, info)
- return resp.blob()
- }
-
- /**
- * Get response data as JSON object.
- * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
- * @param {RNFetchBlobResponseInfo} info Response informations.
- * @return {Promise<object>}
- */
- function readJSON(resp, info):Promise<object> {
- log.verbose('readJSON', resp, info)
- switch (info.rnfbEncode) {
- case 'base64':
- return Promise.resolve(resp.json())
- case 'path':
- return resp.json()
- default:
- return Promise.resolve(resp.json())
- }
- }
|