UNPKG

3.38 kBPlain TextView Raw
1/**
2 * This file is copied from https://github.com/react-component/upload/blob/master/src/request.js
3 * Thanks the authors.
4 */
5
6export type UploadProgressEvent = ProgressEvent & {percent: number};
7
8export interface RequestResult {
9 status: number;
10 statusText: string;
11 data: any,
12 headers: any,
13 xhr: XMLHttpRequest,
14}
15
16export interface RequestOptions {
17 onProgress?: (e: UploadProgressEvent) => void;
18 onError: (error, body?: object) => void;
19 // onSuccess: (body: object, xhr: XMLHttpRequest) => void;
20 onSuccess: (result, xhr: XMLHttpRequest) => void;
21 onAbort?: () => void;
22 data?: Document | BodyInit | null;
23 // filename?: string; // XXX
24 // file?: File; // XXX
25 withCredentials?: boolean;
26 // action: string;
27 headers?:object;
28 method?: string;
29 timeout?: number;
30}
31
32type RequestError = Error & {status?: number; method?: string; url?: string; code?:string};
33
34function getError(url, option, xhr) {
35 const codePart = xhr.response.match(/<Code>(.+)<\/Code>/);
36 const messagePart = xhr.response.match(/<Message>(.+)<\/Message>/);
37
38 const method = option.method || 'GET';
39 // let msg = `[${xhr.status}] ${method} ${url}`;
40 let msg = '';
41 if (codePart && codePart[1]) msg += `${codePart[1]}: `;
42 if (messagePart && messagePart[1]) msg += messagePart[1];
43 const err: RequestError = new Error(msg);
44 err.status = xhr.status;
45 err.method = method;
46 err.code = codePart && codePart[1] || '';
47 err.url = url;
48 return err;
49}
50
51function getBody(xhr) {
52 const text = xhr.responseText || xhr.response;
53 if (!text) {
54 return text;
55 }
56
57 try {
58 return JSON.parse(text);
59 } catch (e) {
60 return text;
61 }
62}
63
64export default function request (url: string, options: RequestOptions) {
65 const xhr = new XMLHttpRequest();
66
67 xhr.timeout = options.timeout || 60_000;
68
69 if (options.onProgress && xhr.upload){
70 xhr.upload.onprogress = function progress(e: UploadProgressEvent) {
71 e.percent = e.loaded / e.total * 100;
72 options.onProgress(e);
73 }
74 }
75
76 /*
77 const formData = new FormData();
78 if (options.data){
79 Object.keys(options.data).forEach(key => {
80 formData.append(key, options.data[key]);
81 })
82 }
83 formData.append(options.filename, options.file);
84 */
85
86 xhr.onerror = function (e) {
87 options.onError(e);
88 };
89
90 xhr.onload = function onload() {
91 if (xhr.status < 200 || xhr.status >= 300) {
92 return options.onError(getError(url, options, xhr), getBody(xhr));
93 }
94 const result = {
95 status: xhr.status,
96 statusText: xhr.statusText,
97 xhr,
98 data: getBody(xhr),
99 };
100 options.onSuccess(result, xhr);
101 };
102
103 xhr.ontimeout = function timeout(ev){
104 const err: Error = new Error(`Request timeout, limit ${xhr.timeout} ms.`);
105 options.onError(err);
106 };
107
108 if (options.onAbort) xhr.onabort = options.onAbort;
109
110 xhr.open(options.method || 'get', url, true);
111
112
113 if (options.withCredentials && 'withCredentials' in xhr) {
114 xhr.withCredentials = true;
115 }
116
117 const headers = options.headers || {};
118
119 if (headers['X-Requested-With'] !== null) {
120 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
121 }
122
123 for (const h in headers){
124 if (headers.hasOwnProperty(h) && headers[h] !== null){
125 xhr.setRequestHeader(h, headers[h]);
126 }
127 }
128 // xhr.send(formData);
129 xhr.send(options.data || null);
130
131 return {
132 abort() {
133 xhr.abort();
134 },
135 }
136}