source: imaps-frontend/node_modules/axios/lib/adapters/fetch.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 6.5 KB
RevLine 
[d565449]1import platform from "../platform/index.js";
2import utils from "../utils.js";
3import AxiosError from "../core/AxiosError.js";
4import composeSignals from "../helpers/composeSignals.js";
5import {trackStream} from "../helpers/trackStream.js";
6import AxiosHeaders from "../core/AxiosHeaders.js";
7import {progressEventReducer, progressEventDecorator, asyncDecorator} from "../helpers/progressEventReducer.js";
8import resolveConfig from "../helpers/resolveConfig.js";
9import settle from "../core/settle.js";
10
11const isFetchSupported = typeof fetch === 'function' && typeof Request === 'function' && typeof Response === 'function';
12const isReadableStreamSupported = isFetchSupported && typeof ReadableStream === 'function';
13
14// used only inside the fetch adapter
15const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ?
16 ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) :
17 async (str) => new Uint8Array(await new Response(str).arrayBuffer())
18);
19
20const test = (fn, ...args) => {
21 try {
22 return !!fn(...args);
23 } catch (e) {
24 return false
25 }
26}
27
28const supportsRequestStream = isReadableStreamSupported && test(() => {
29 let duplexAccessed = false;
30
31 const hasContentType = new Request(platform.origin, {
32 body: new ReadableStream(),
33 method: 'POST',
34 get duplex() {
35 duplexAccessed = true;
36 return 'half';
37 },
38 }).headers.has('Content-Type');
39
40 return duplexAccessed && !hasContentType;
41});
42
43const DEFAULT_CHUNK_SIZE = 64 * 1024;
44
45const supportsResponseStream = isReadableStreamSupported &&
46 test(() => utils.isReadableStream(new Response('').body));
47
48
49const resolvers = {
50 stream: supportsResponseStream && ((res) => res.body)
51};
52
53isFetchSupported && (((res) => {
54 ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => {
55 !resolvers[type] && (resolvers[type] = utils.isFunction(res[type]) ? (res) => res[type]() :
56 (_, config) => {
57 throw new AxiosError(`Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config);
58 })
59 });
60})(new Response));
61
62const getBodyLength = async (body) => {
63 if (body == null) {
64 return 0;
65 }
66
67 if(utils.isBlob(body)) {
68 return body.size;
69 }
70
71 if(utils.isSpecCompliantForm(body)) {
72 const _request = new Request(platform.origin, {
73 method: 'POST',
74 body,
75 });
76 return (await _request.arrayBuffer()).byteLength;
77 }
78
79 if(utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {
80 return body.byteLength;
81 }
82
83 if(utils.isURLSearchParams(body)) {
84 body = body + '';
85 }
86
87 if(utils.isString(body)) {
88 return (await encodeText(body)).byteLength;
89 }
90}
91
92const resolveBodyLength = async (headers, body) => {
93 const length = utils.toFiniteNumber(headers.getContentLength());
94
95 return length == null ? getBodyLength(body) : length;
96}
97
98export default isFetchSupported && (async (config) => {
99 let {
100 url,
101 method,
102 data,
103 signal,
104 cancelToken,
105 timeout,
106 onDownloadProgress,
107 onUploadProgress,
108 responseType,
109 headers,
110 withCredentials = 'same-origin',
111 fetchOptions
112 } = resolveConfig(config);
113
114 responseType = responseType ? (responseType + '').toLowerCase() : 'text';
115
116 let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
117
118 let request;
119
120 const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
121 composedSignal.unsubscribe();
122 });
123
124 let requestContentLength;
125
126 try {
127 if (
128 onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' &&
129 (requestContentLength = await resolveBodyLength(headers, data)) !== 0
130 ) {
131 let _request = new Request(url, {
132 method: 'POST',
133 body: data,
134 duplex: "half"
135 });
136
137 let contentTypeHeader;
138
139 if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
140 headers.setContentType(contentTypeHeader)
141 }
142
143 if (_request.body) {
144 const [onProgress, flush] = progressEventDecorator(
145 requestContentLength,
146 progressEventReducer(asyncDecorator(onUploadProgress))
147 );
148
149 data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
150 }
151 }
152
153 if (!utils.isString(withCredentials)) {
154 withCredentials = withCredentials ? 'include' : 'omit';
155 }
156
157 // Cloudflare Workers throws when credentials are defined
158 // see https://github.com/cloudflare/workerd/issues/902
159 const isCredentialsSupported = "credentials" in Request.prototype;
160 request = new Request(url, {
161 ...fetchOptions,
162 signal: composedSignal,
163 method: method.toUpperCase(),
164 headers: headers.normalize().toJSON(),
165 body: data,
166 duplex: "half",
167 credentials: isCredentialsSupported ? withCredentials : undefined
168 });
169
170 let response = await fetch(request);
171
172 const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response');
173
174 if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
175 const options = {};
176
177 ['status', 'statusText', 'headers'].forEach(prop => {
178 options[prop] = response[prop];
179 });
180
181 const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
182
183 const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
184 responseContentLength,
185 progressEventReducer(asyncDecorator(onDownloadProgress), true)
186 ) || [];
187
188 response = new Response(
189 trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
190 flush && flush();
191 unsubscribe && unsubscribe();
192 }),
193 options
194 );
195 }
196
197 responseType = responseType || 'text';
198
199 let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);
200
201 !isStreamResponse && unsubscribe && unsubscribe();
202
203 return await new Promise((resolve, reject) => {
204 settle(resolve, reject, {
205 data: responseData,
206 headers: AxiosHeaders.from(response.headers),
207 status: response.status,
208 statusText: response.statusText,
209 config,
210 request
211 })
212 })
213 } catch (err) {
214 unsubscribe && unsubscribe();
215
216 if (err && err.name === 'TypeError' && /fetch/i.test(err.message)) {
217 throw Object.assign(
218 new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request),
219 {
220 cause: err.cause || err
221 }
222 )
223 }
224
225 throw AxiosError.from(err, err && err.code, config, request);
226 }
227});
228
229
Note: See TracBrowser for help on using the repository browser.