From 001100c91330656ddf686c51029e05bea70a4655 Mon Sep 17 00:00:00 2001 From: kuu Date: Mon, 24 Oct 2022 12:02:28 +0800 Subject: [PATCH 1/2] feat: use AbortController, fix multipart boundary --- index.js | 99 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index 476331f..5bbcfa5 100644 --- a/index.js +++ b/index.js @@ -11,31 +11,69 @@ import { isUndefined, isStandardBrowserEnv, isFormData } from 'axios/lib/utils'; */ export default async function fetchAdapter(config) { const request = createRequest(config); - const promiseChain = [getResponse(request, config)]; - - if (config.timeout && config.timeout > 0) { - promiseChain.push( - new Promise((res) => { - setTimeout(() => { - const message = config.timeoutErrorMessage - ? config.timeoutErrorMessage - : 'timeout of ' + config.timeout + 'ms exceeded'; - res(createError(message, config, 'ECONNABORTED', request)); - }, config.timeout); - }) - ); + const stageOne = await startFetch(request, config); + const data = getResponse(stageOne) + const theSettle = config.settle instanceof Function + ? config.settle + : settle; + return new Promise((resolve, reject) => { + theSettle(resolve, reject, data); + }) +} + +async function startFetch(request, config) { + const createNetworkError = () => { + const networkError = createError('Network Error', config, 'ERR_NETWORK', request); + return networkError; } - const data = await Promise.race(promiseChain); - return new Promise((resolve, reject) => { - if (data instanceof Error) { - reject(data); - } else { - Object.prototype.toString.call(config.settle) === '[object Function]' - ? config.settle(resolve, reject, data) - : settle(resolve, reject, data); + if (typeof config.time !== 'number' || isNaN(config.time) || config.time <= 0) { + try { + return await fetch(request); + } catch { + throw createNetworkError(); + } + } + + const createTimeoutError = () => { + const message = config.timeoutErrorMessage + ? config.timeoutErrorMessage + : 'timeout of ' + config.timeout + 'ms exceeded'; + const timeoutError = createError(message, config, 'ECONNABORTED', request); + return timeoutError; + }; + + try { + var abortController = new AbortController() + } catch (error) { + return new Promise(async(resolve, reject) => { + const rejectTimeout = () => { + reject(createTimeoutError()) + }; + setTimeout(rejectTimeout, time); + try { + resolve(await fetch(request)); + } catch(error) { + rejectTimeout(); + } + }) + } + + setTimeout(() => { + abortController.abort() + }, config.timeout); + + try { + return await fetch(request, { + signal: abortController.signal + }); + } catch (error) { + if (abortController.signal.aborted) { + throw createTimeoutError(); } - }); + + throw createNetworkError(); + } } @@ -43,14 +81,7 @@ export default async function fetchAdapter(config) { * Fetch API stage two is to get response body. This funtion tries to retrieve * response body based on response's type */ -async function getResponse(request, config) { - let stageOne; - try { - stageOne = await fetch(request); - } catch (e) { - return createError('Network Error', config, 'ERR_NETWORK', request); - } - +async function getResponse(stageOne, config) { const response = { ok: stageOne.ok, status: stageOne.status, @@ -87,6 +118,14 @@ async function getResponse(request, config) { * This function will create a Request object based on configuration's axios */ function createRequest(config) { + // Fix bug https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post + if (config.data instanceof FormData && config.headers) { + const ContentType = 'Content-Type'; + delete config.headers[ContentType]; + delete config.headers[ContentType.toLowerCase()]; + delete config.headers[ContentType.toUpperCase()]; + } + const headers = new Headers(config.headers); // HTTP basic authentication From 41f52cd7da821345b1ae85c0a4c3812b244dcb6b Mon Sep 17 00:00:00 2001 From: kuu Date: Mon, 24 Oct 2022 18:05:42 +0800 Subject: [PATCH 2/2] fix: error type --- index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 5bbcfa5..5f39fe4 100644 --- a/index.js +++ b/index.js @@ -47,14 +47,14 @@ async function startFetch(request, config) { var abortController = new AbortController() } catch (error) { return new Promise(async(resolve, reject) => { - const rejectTimeout = () => { + setTimeout(() => { reject(createTimeoutError()) - }; - setTimeout(rejectTimeout, time); + }, time); + try { resolve(await fetch(request)); - } catch(error) { - rejectTimeout(); + } catch (error) { + reject(createNetworkError()); } }) }