Skip to content

Instantly share code, notes, and snippets.

@veggiemonk
Last active March 13, 2020 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veggiemonk/18b8fbab0469f3b2ee6ac23cd00e89b3 to your computer and use it in GitHub Desktop.
Save veggiemonk/18b8fbab0469f3b2ee6ac23cd00e89b3 to your computer and use it in GitHub Desktop.
fetch boilerplate
/**
* readRequestBody reads in the incoming request body
* Use await readRequestBody(..) in an async function to get the string
* @param {Request} request the incoming request to read from
*/
export async function readRequestBody(request:Request) {
const { headers } = request
const contentType = headers.get('content-type')
if (contentType != null) {
if (contentType.includes('application/json')) {
const body = await request.json()
return JSON.stringify(body)
} else if (contentType.includes('application/text')) {
const body = await request.text()
return body
} else if (contentType.includes('text/html')) {
const body = await request.text()
return body
} else if (contentType.includes('form')) {
const formData = await request.formData()
const body = {}
for (let [key, value] of formData.entries()) {
if (Array.isArray(body[key])) body[key].push(value)
else if (body[key] !== undefined) body[key] = [body[key], value]
else body[key] = value
}
return JSON.stringify(body)
}
}
const myBlob = await request.blob()
return URL.createObjectURL(myBlob)
}
/**
* gatherResponse awaits and returns a response body as a string.
* Use await gatherResponse(..) in an async function to get the response body
* @param {Response} response to
*/
export async function gatherResponse(response: Response) {
const { headers } = response
const contentType = headers.get('content-type')
if (contentType != null) {
if (contentType.includes('application/json')) {
const body = await response.json()
return JSON.stringify(body)
} else if (contentType.includes('application/text')) {
const body = await response.text()
return body
} else if (contentType.includes('text/html')) {
const body = await response.text()
return body
}
}
const body = await response.text()
return body
}
/**
* fetchPostJson sends a POST request with data in JSON and
* and reads in the response body. Use await fetchPostJson(..)
* in an async function to get the response body
* @param {string} url the URL to send the request to
* @param {BodyInit} body the JSON data to send in the request
*/
export async function fetchPostJson(url:string, body:unknown = {}) {
const init = {
body: JSON.stringify(body),
method: 'POST',
headers: {
'content-type': 'application/json;charset=UTF-8',
},
}
const response = await fetch(url, init)
return await gatherResponse(response)
}
/**
* fetchGetHtml sends a GET request expecting html
* Use await fetchGetHtml(..) in an async function to get the HTML
* @param {string} url the URL to send the request to
*/
export async function fetchGetHtml(url:string) {
const init = {
method: 'Get',
headers: {
'content-type': 'text/html;charset=UTF-8',
},
}
const response = await fetch(url, init)
return await gatherResponse(response)
}
import httpStatus from "http-status";
import fetch from "node-fetch";
import * as R from "ramda";
import { isNilOrEmpty } from "../utils/helper";
const getResponseBody = (contentType = "", response) => {
if (contentType.includes("text/plain")) {
return response.text();
}
if (contentType.includes("application/json")) {
return response.json();
}
if (contentType.includes("application/octet-stream")) {
return response.blob();
}
return response.text();
};
const handleSuccessResponse = async (contentType, response) => {
let returnObj = {};
if (response.status === httpStatus.NO_CONTENT) {
return returnObj;
}
if (contentType.includes("application/octet-stream")) {
const blobData = await getResponseBody(contentType, response);
returnObj = { url: URL.createObjectURL(blobData) };
} else {
returnObj = await getResponseBody(contentType, response);
}
return returnObj;
};
const handleFailureResponse = async (contentType, response) => {
let returnObj = {};
let errorDataFromServer = null;
if (contentType.includes("application/octet-stream")) {
const blobData = await getResponseBody(contentType, response);
errorDataFromServer = { url: URL.createObjectURL(blobData) };
} else {
errorDataFromServer = await getResponseBody(contentType, response);
}
// if response is failed and does not contain the error Msg
// assign the default Error Msg as Failed Response Status
if (R.isNil(errorDataFromServer) || R.isNil(errorDataFromServer.error)) {
returnObj.error = httpStatus[response.status];
} else {
returnObj = errorDataFromServer;
}
return returnObj;
};
const responseHandler = async (response, resolve, reject) => {
const metaData = {
responseStatus: response.status
};
let returnObj = {};
try {
let contentType = response.headers.get("content-type") || "";
if (contentType) {
contentType = contentType.toLowerCase();
}
if (response.ok) {
returnObj = await handleSuccessResponse(contentType, response);
returnObj = R.merge(returnObj, metaData);
return resolve(returnObj);
}
returnObj = await handleFailureResponse(contentType, response);
returnObj = R.merge(returnObj, metaData);
return reject(returnObj);
} catch (error) {
returnObj.error = error.message ? error.message : true;
returnObj = R.merge(returnObj, metaData);
return reject(returnObj);
}
};
function getBaseApiEndPoint() {
console.log("%c process.env ", "background: aqua; color: black", process.env);
if (process.env.REACT_APP_API_URL) {
return process.env.REACT_APP_API_URL;
}
return "";
}
export async function callApi(apiObject) {
const fetchObject = {};
let body = {};
fetchObject.method = apiObject.method ? apiObject.method : "GET";
// if apiObject contains authenticationRequired(true/false),
// which indicate, whether we need to send the token with the api Call or not
// if apiObject does not contains authentication property,
// than by default we are sending the token
let isAuthenticationRequired = true;
if (typeof apiObject.authenticationRequired === "boolean") {
isAuthenticationRequired = apiObject.authenticationRequired;
}
fetchObject.headers = {
Accept: "application/json",
"Content-Type": "application/json"
};
fetchObject.headers = apiObject.headers
? { ...fetchObject.headers, ...apiObject.headers }
: { ...fetchObject.headers };
if (
fetchObject.headers["Content-Type"] &&
(fetchObject.headers["Content-Type"] === "application/xml" ||
fetchObject.headers["Content-Type"] === "text/xml")
) {
body = apiObject.body ? apiObject.body : {};
} else {
body = apiObject.body ? JSON.stringify(apiObject.body) : {};
}
if (fetchObject.method === "GET") {
fetchObject.body = undefined;
} else {
fetchObject.body = body;
}
if (isAuthenticationRequired) {
// if headers.authorization is null, ie no token is present in the headers object
// then get the stored token, else use token which is present
// in the headers authorization property
if (isNilOrEmpty(fetchObject.headers.authorization)) {
const token = localStorage.getItem("AUTH_TOKEN");
fetchObject.headers.authorization = `BEARER ${token}`;
}
}
const url = `${getBaseApiEndPoint()}/${apiObject.endPoint}`;
return new Promise(async (resolve, reject) => {
try {
const fetchResult = await fetch(url, fetchObject);
return responseHandler(fetchResult, resolve, reject);
} catch (err) {
return reject({
error: "someThing Unexpected Happened",
msg: err.message || "Something Went Wrong"
});
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment