// $Id: RestServices.js 8623 2025-09-08 14:34:47Z jochen.hanff $
// // @ts-check
"use strict";
import { ApiResponse } from "./ApiResponse.js"
/**
* @fileoverview Rest services for making HTTP API calls.
* Types and services to manage HTTP API calls.
*/
/**
*
* @category Tools
*
* @classdesc Helper class for response of a REST call.
* @property {number} status HTTP status code (getter)
* @property {*} data Parsed response body (getter)
* @property {string|null} contentType Content-Type header (getter)
* @property {string|null} message Human readable status (getter)
*
*/
export class RestResponse extends ApiResponse {
#_contentType = null;
/**
*
* @param {*} status REST status code
* @param {*} responsedata Response as JSON object
* @param {string|null} contentType
* @param {string|null} message Optional message
*/
constructor(status, responsedata, contentType, message = null) {
super(status, responsedata, message);
this.#_contentType = contentType;
}
/**
* @returns {string|null}
*/
get getContentType() {
return this.#_contentType;
}
}
/**
* @category Tools
*
* @classdesc Helper class for Rest services. <br>
* Provides methods such as for making HTTP API calls.
*
*/
export class RestServices {
constructor() {}
/**
* Supported HTTP methods. <br>
* GET / POST / PUT / DELETE / PATCH
*
* @example
* // call REST service
* const url = `${ctx.getServiceUrl(InfohubContext.SERVICE.USR)}/${cntx.getScope()}/usergroups?filter=$userid ~eq~ '${userid}'&members=info`;
* let resp = RestServices.makeApiCall( ctx.getToken(), RestServices.METHODS.GET , url);
* @readonly
*
*/
static METHODS = {
GET: "GET",
POST: "POST",
PUT: "PUT",
DELETE: "DELETE",
PATCH: "PATCH",
};
/**
*
* Make HTTP API call.
* Uses 'fetch' to execute the call.
*
* @example
* //
* const url = `${ctx.getServiceUrl(InfohubContext.SERVICE.USR)}/${ctx.getScope()}/usergroups?filter=$userid ~eq~ '${userid}'&members=info`;
* let resp = RestServices.makeApiCall( ctx.getToken(), RestServices.METHODS.GET , url);
*
* @param {string} token The access token to use for the API call
* @param {string} method HTTP method
* @param {string} fullpath URL of endpoint
* @param {Object} body = null, Request Body, Could be null for GET
* @param {string} acceptType = "application/json",
* Accept: acceptType // Accept Header
* @param {string} contentType = "application/json"
* Content-Type header
* @param {string} responseType "auto" // "auto" | "json" | "text" | "blob" | "arrayBuffer"
* Response type
*
* @returns {Promise<RestResponse>}
*
*/
static async makeApiCall(
token,
method,
fullpath,
body = null,
acceptType = "application/json",
contentType = "application/json",
responseType = "auto" // "auto" | "json" | "text" | "blob" | "arrayBuffer"
) {
const url = fullpath;
const headers = {
Authorization: `Bearer ${token}`,
Accept: acceptType,
};
// Only set Content-Type if sending a body
if (body != null) headers["Content-Type"] = contentType;
const options = { method, headers };
if (
body &&
(method === RestServices.METHODS.POST ||
method === RestServices.METHODS.PATCH ||
method === RestServices.METHODS.PUT)
) {
options.body =
contentType && contentType.includes("application/json")
? JSON.stringify(body)
: body;
}
try {
console.log("fetch ...");
const response = await fetch(url, options);
const ct = response.headers.get("content-type") || "";
let data;
if (
responseType === "blob" ||
ct.startsWith("image/") ||
ct.includes("octet-stream")
) {
data = await response.blob();
} else if (responseType === "arrayBuffer") {
data = await response.arrayBuffer();
} else if (responseType === "text" || ct.startsWith("text/")) {
data = await response.text();
} else {
// default json, but tolerate non-json
try {
data = await response.json();
} catch {
data = await response.text();
}
}
// return RestResponse(
// status: response.status,
// ok: response.ok,
// data,
// contentType: ct,
// message: response.ok
// ? "Success"
// : `HTTP ${response.status}: ${response.statusText}`,
// );
let msg = null;
if (response.ok) {
msg = "Success";
} else {
msg = `HTTP ${response.status}: ${response.statusText}`;
}
return new RestResponse(response.status, data, ct, msg);
} catch (error) {
console.error(`API call failed: ${method} ${url}`, error);
return new RestResponse(500, null, null, error.message);
}
}
}
Source