forked from microsoftgraph/msgraph-sdk-javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGraphResponseHandler.ts
More file actions
166 lines (158 loc) · 5.29 KB
/
Copy pathGraphResponseHandler.ts
File metadata and controls
166 lines (158 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/
/**
* @module GraphResponseHandler
*/
import { GraphRequestCallback } from "./IGraphRequestCallback";
import { ResponseType } from "./ResponseType";
/**
* @enum
* Enum for document types
* @property {string} TEXT_HTML - The text/html content type
* @property {string} TEXT_XML - The text/xml content type
* @property {string} APPLICATION_XML - The application/xml content type
* @property {string} APPLICATION_XHTML - The application/xhml+xml content type
*/
enum DocumentType {
TEXT_HTML = "text/html",
TEXT_XML = "text/xml",
APPLICATION_XML = "application/xml",
APPLICATION_XHTML = "application/xhtml+xml",
}
/**
* @class
* Class for GraphResponseHandler
*/
export class GraphResponseHandler {
/**
* @private
* @static
* A member holding array of document types
*/
private static DocumentTypes: string[] = ["text/html", "text/xml", "application/xml", "application/xhtml+xml"];
/**
* @private
* @static
* To parse Document response
* @param {Response} rawResponse - The response object
* @param {DocumentType} type - The type to which the document needs to be parsed
* @returns A promise that resolves to a document content
*/
private static parseDocumentResponse(rawResponse: Response, type: DocumentType): Promise<any> {
if (typeof DOMParser !== "undefined") {
return new Promise((resolve, reject) => {
rawResponse.text().then((xmlString) => {
try {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, type);
resolve(xmlDoc);
} catch (error) {
reject(error);
}
});
});
} else {
return Promise.resolve(rawResponse.body);
}
}
/**
* @private
* @static
* @async
* To convert the native Response to response content
* @param {Response} rawResponse - The response object
* @param {ResponseType} [responseType] - The response type value
* @returns A promise that resolves to the converted response content
*/
private static async convertResponse(rawResponse: Response, responseType?: ResponseType): Promise<any> {
if (responseType === ResponseType.RAW) {
return Promise.resolve(rawResponse);
}
if (rawResponse.status === 204) {
// NO CONTENT
return Promise.resolve();
}
let responseValue: any;
try {
switch (responseType) {
case ResponseType.ARRAYBUFFER:
responseValue = await rawResponse.arrayBuffer();
break;
case ResponseType.BLOB:
responseValue = await rawResponse.blob();
break;
case ResponseType.DOCUMENT:
responseValue = await GraphResponseHandler.parseDocumentResponse(rawResponse, DocumentType.TEXT_XML);
break;
case ResponseType.JSON:
responseValue = await rawResponse.json();
break;
case ResponseType.STREAM:
responseValue = await Promise.resolve(rawResponse.body);
break;
case ResponseType.TEXT:
responseValue = await rawResponse.text();
break;
default:
const contentType = rawResponse.headers.get("Content-type");
if (contentType !== null) {
const mimeType = contentType.split(";")[0];
responseValue = GraphResponseHandler.DocumentTypes.includes(mimeType) ? await GraphResponseHandler.parseDocumentResponse(rawResponse, mimeType as DocumentType) : await rawResponse.json();
} else {
/**
* RFC specification {@link https://tools.ietf.org/html/rfc7231#section-3.1.1.5} says:
* A sender that generates a message containing a payload body SHOULD
* generate a Content-Type header field in that message unless the
* intended media type of the enclosed representation is unknown to the
* sender. If a Content-Type header field is not present, the recipient
* MAY either assume a media type of "application/octet-stream"
* ([RFC2046], Section 4.5.1) or examine the data to determine its type.
*
* So assuming it as a stream type so returning the body.
*/
responseValue = Promise.resolve(rawResponse.body);
}
break;
}
} catch (error) {
if (typeof responseType !== "undefined" && responseType !== ResponseType.JSON) {
responseValue = await rawResponse.json();
} else {
throw error;
}
}
return responseValue;
}
/**
* @public
* @static
* @async
* To get the parsed response
* @param {Response} rawResponse - The response object
* @param {ResponseType} [responseType] - The response type value
* @param {GraphRequestCallback} [callback] - The graph request callback function
* @returns The parsed response
*/
public static async getResponse(rawResponse: Response, responseType?: ResponseType, callback?: GraphRequestCallback): Promise<any> {
try {
const response = await GraphResponseHandler.convertResponse(rawResponse, responseType);
if (rawResponse.ok) {
// Status Code 2XX
if (typeof callback === "function") {
callback(null, response, rawResponse);
} else {
return response;
}
} else {
// NOT OK Response
throw response;
}
} catch (error) {
throw error;
}
}
}