xref: /aosp_15_r20/development/tools/winscope/src/common/http_request.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright 2024, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {assertDefined} from 'common/assert_utils';
18
19export type HttpRequestHeaderType = Array<[string, string]>;
20
21export enum HttpRequestStatus {
22  UNSENT,
23  UNAUTH,
24  SUCCESS,
25  ERROR,
26}
27
28export interface HttpResponse {
29  status: HttpRequestStatus;
30  type: XMLHttpRequestResponseType; //eslint-disable-line no-undef
31  text: string;
32  body: any;
33  getHeader: (name: string) => string | undefined;
34}
35
36export class HttpRequest {
37  static async get(
38    path: string,
39    headers: HttpRequestHeaderType,
40    type?: XMLHttpRequest['responseType'],
41  ): Promise<HttpResponse> {
42    return await HttpRequest.call('GET', path, headers, type);
43  }
44
45  static async post(
46    path: string,
47    headers: HttpRequestHeaderType,
48    jsonRequest?: object,
49  ): Promise<HttpResponse> {
50    return await HttpRequest.call(
51      'POST',
52      path,
53      headers,
54      undefined,
55      jsonRequest,
56    );
57  }
58
59  private static async call(
60    method: string,
61    path: string,
62    headers: HttpRequestHeaderType,
63    type?: XMLHttpRequest['responseType'],
64    jsonRequest?: object,
65  ): Promise<HttpResponse> {
66    const req = new XMLHttpRequest();
67    let status: HttpRequestStatus | undefined;
68
69    await new Promise<void>((resolve) => {
70      req.onreadystatechange = async () => {
71        if (req.readyState !== XMLHttpRequest.DONE) {
72          return;
73        }
74        if (req.status === XMLHttpRequest.UNSENT) {
75          status = HttpRequestStatus.UNSENT;
76        } else if (req.status === 200) {
77          status = HttpRequestStatus.SUCCESS;
78        } else if (req.status === 403) {
79          status = HttpRequestStatus.UNAUTH;
80        } else {
81          status = HttpRequestStatus.ERROR;
82        }
83        resolve();
84      };
85      req.responseType = type || '';
86      req.open(method, path);
87      headers.forEach(([header, value]) => {
88        req.setRequestHeader(header, value);
89      });
90
91      if (jsonRequest) {
92        const json = JSON.stringify(jsonRequest);
93        req.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
94        req.send(json);
95      } else {
96        req.send();
97      }
98    });
99
100    const hasResponseText =
101      req.responseType === '' || req.responseType === 'text';
102
103    return {
104      status: assertDefined(status),
105      type: req.responseType,
106      text: hasResponseText ? req.responseText : '',
107      body: req.response,
108      getHeader: (name: string) => req.getResponseHeader(name) ?? undefined,
109    };
110  }
111}
112