core-native
Version:
A lightweight framework based on React Native + Redux + Redux Saga, in strict TypeScript.
110 lines • 4.85 kB
JavaScript
/**
* Attention:
* Do NOT use "axios" for network utils in React Native.
*
* Explanation:
* 1) Axios supports [nodejs-http] and [XHR] only, does not support [fetch] API.
* 2) Although React Native has a XHR-same interface, but it has a bit difference on CORS policy.
* 3) If XHR is used in React Native (i.e, what axios does), customized response header cannot be retrieved.
*
* Ref:
* https://stackoverflow.com/questions/37897523/axios-get-access-to-response-header-fields
*/
import { __awaiter } from "tslib";
import { APIException, NetworkConnectionException } from "../Exception";
import { parseWithDate } from "./json-util";
const networkInterceptor = {};
export function setRequestHeaderInterceptor(_) {
networkInterceptor.request = _;
}
export function setResponseHeaderInterceptor(_) {
networkInterceptor.response = _;
}
export function ajax(method, path, pathParams, request, skipInterceptor = false) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
let requestURL = urlParams(path, pathParams);
const requestHeaders = new Headers({
"Content-Type": "application/json",
Accept: "application/json",
});
if (!skipInterceptor) {
yield ((_a = networkInterceptor.request) === null || _a === void 0 ? void 0 : _a.call(networkInterceptor, requestHeaders));
}
const requestParameters = { method, headers: requestHeaders };
if (request) {
if (method === "GET" || method === "DELETE") {
requestURL += queryString(request);
}
else {
requestParameters.body = JSON.stringify(request);
}
}
try {
const response = yield fetch(requestURL, requestParameters);
if (!skipInterceptor) {
yield ((_b = networkInterceptor.response) === null || _b === void 0 ? void 0 : _b.call(networkInterceptor, response.headers));
}
const responseText = yield response.text();
// API response may be void, in such case, JSON.parse will throw error
const responseData = responseText ? parseWithDate(responseText) : {};
if (response.ok) {
// HTTP Status 200
return responseData;
}
else {
// Try to get server errorMessage from response
const apiErrorResponse = responseData;
const errorId = (apiErrorResponse === null || apiErrorResponse === void 0 ? void 0 : apiErrorResponse.id) || null;
const errorCode = (apiErrorResponse === null || apiErrorResponse === void 0 ? void 0 : apiErrorResponse.errorCode) || null;
if (!errorId && (response.status === 502 || response.status === 504)) {
// Treat "cloud" error as Network Exception, e.g: gateway issue, load balancer unconnected to application server
// Note: Status 503 is maintenance
throw new NetworkConnectionException(`Gateway error (${response.status})`, requestURL);
}
else {
const errorMessage = responseData && responseData.message ? responseData.message : `[No Response]`;
throw new APIException(errorMessage, response.status, requestURL, responseData, errorId, errorCode);
}
}
}
catch (e) {
// Only APIException, NetworkConnectionException can be thrown
if (e instanceof APIException || e instanceof NetworkConnectionException) {
throw e;
}
else {
throw new NetworkConnectionException(`Failed to connect: ${requestURL}`, requestURL, e instanceof Error ? e.message : "[Unknown]");
}
}
});
}
export function uri(path, request) {
return path + queryString(request);
}
export function urlParams(path, params) {
let pathWithParams = path;
Object.entries(params).forEach(([name, value]) => {
const encodedValue = encodeURIComponent(value.toString());
pathWithParams = pathWithParams.replace(":" + name, encodedValue);
});
return pathWithParams;
}
export function queryString(params) {
if (!params) {
return "";
}
const entries = Object.entries(params);
if (entries.length === 0) {
return "";
}
return ("?" +
entries
.filter((_) => _[1] !== null) // If some value is NULL, do not append to URL
.map(([key, value]) => {
const valueString = value instanceof Date ? value.toISOString() : encodeURIComponent(String(value));
return `${encodeURIComponent(key)}=${valueString}`;
})
.join("&"));
}
//# sourceMappingURL=network.js.map