1 |
|
2 |
|
3 |
|
4 | import { AbortError, HttpError, TimeoutError } from "./Errors";
|
5 | import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient";
|
6 | import { ILogger, LogLevel } from "./ILogger";
|
7 |
|
8 | export class XhrHttpClient extends HttpClient {
|
9 | private readonly logger: ILogger;
|
10 |
|
11 | public constructor(logger: ILogger) {
|
12 | super();
|
13 | this.logger = logger;
|
14 | }
|
15 |
|
16 |
|
17 | public send(request: HttpRequest): Promise<HttpResponse> {
|
18 |
|
19 | if (request.abortSignal && request.abortSignal.aborted) {
|
20 | return Promise.reject(new AbortError());
|
21 | }
|
22 |
|
23 | if (!request.method) {
|
24 | return Promise.reject(new Error("No method defined."));
|
25 | }
|
26 | if (!request.url) {
|
27 | return Promise.reject(new Error("No url defined."));
|
28 | }
|
29 |
|
30 | return new Promise<HttpResponse>((resolve, reject) => {
|
31 | const xhr = new XMLHttpRequest();
|
32 |
|
33 | xhr.open(request.method!, request.url!, true);
|
34 | xhr.withCredentials = true;
|
35 | xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
36 |
|
37 | xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
|
38 |
|
39 | const headers = request.headers;
|
40 | if (headers) {
|
41 | Object.keys(headers)
|
42 | .forEach((header) => {
|
43 | xhr.setRequestHeader(header, headers[header]);
|
44 | });
|
45 | }
|
46 |
|
47 | if (request.responseType) {
|
48 | xhr.responseType = request.responseType;
|
49 | }
|
50 |
|
51 | if (request.abortSignal) {
|
52 | request.abortSignal.onabort = () => {
|
53 | xhr.abort();
|
54 | reject(new AbortError());
|
55 | };
|
56 | }
|
57 |
|
58 | if (request.timeout) {
|
59 | xhr.timeout = request.timeout;
|
60 | }
|
61 |
|
62 | xhr.onload = () => {
|
63 | if (request.abortSignal) {
|
64 | request.abortSignal.onabort = null;
|
65 | }
|
66 |
|
67 | if (xhr.status >= 200 && xhr.status < 300) {
|
68 | resolve(new HttpResponse(xhr.status, xhr.statusText, xhr.response || xhr.responseText));
|
69 | } else {
|
70 | reject(new HttpError(xhr.statusText, xhr.status));
|
71 | }
|
72 | };
|
73 |
|
74 | xhr.onerror = () => {
|
75 | this.logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}.`);
|
76 | reject(new HttpError(xhr.statusText, xhr.status));
|
77 | };
|
78 |
|
79 | xhr.ontimeout = () => {
|
80 | this.logger.log(LogLevel.Warning, `Timeout from HTTP request.`);
|
81 | reject(new TimeoutError());
|
82 | };
|
83 |
|
84 | xhr.send(request.content || "");
|
85 | });
|
86 | }
|
87 | }
|
88 |
|
\ | No newline at end of file |