+
ModernAPIClient Documentation
+
+
+ Overview
+ The ModernAPIClient class is designed to simplify API interactions in a web environment. It supports making GET and POST requests, including handling file uploads and securely managing request parameters.
+
+
+
+ Initialization
+ const client = new ModernAPIClient('https://api.example.com');
+
+
+
+ Memory Optimization and Security
+ When the ModernAPIClient is instantiated, it automatically decrypts and stores certain values (e.g., MemOptimizeMethod and MemStackFrame) that are used to secure API requests. These values are expected to be present as Base64-encoded hidden fields in the HTML page.
+
+
+
+ Methods
+
+ 1. postAction(controller, action, parameters, secure = false)
+ Sends a POST request to a specific controller and action within the API.
+ Parameters:
+
+ controller (string): The controller name.
+ action (string): The action name.
+ parameters (object): An object containing key-value pairs to be sent as the POST body.
+ secure (boolean): If true, the request will be secured with additional parameters.
+
+ Returns: A Promise that resolves with the response data.
+
+ Example:
+ const parameters = { param1: 'value1' };
+client.postAction('exampleController', 'exampleAction', parameters)
+ .then(response => console.log('POST Action Result:', response))
+ .catch(error => console.error('Error in POST Action:', error));
+
+ 2. postFileAction(controller, action, fileName, secure = false)
+ Sends a POST request to upload a file to a specific controller and action within the API.
+ Parameters:
+
+ controller (string): The controller name.
+ action (string): The action name.
+ fileName (string): The file to be uploaded.
+ secure (boolean): If true, the request will be secured with additional parameters.
+
+ Returns: A Promise that resolves with the response data.
+
+ Example:
+ const fileInput = document.getElementById('fileInput');
+const file = fileInput.files[0];
+client.postFileAction('uploadController', 'uploadAction', file)
+ .then(response => console.log('File Upload Result:', response))
+ .catch(error => console.error('Error in File Upload:', error));
+
+ 3. getAction(controller, action, parameters, secure = false)
+ Sends a GET request to a specific controller and action within the API.
+ Parameters:
+
+ controller (string): The controller name.
+ action (string): The action name.
+ parameters (object): An object containing key-value pairs to be sent as query string parameters.
+ secure (boolean): If true, the request will be secured with additional parameters.
+
+ Returns: A Promise that resolves with the response data.
+
+ Example:
+ const parameters = { param1: 'value1' };
+client.getAction('exampleController', 'exampleAction', parameters)
+ .then(response => console.log('GET Action Result:', response))
+ .catch(error => console.error('Error in GET Action:', error));
+
+ 4. getStatic(staticRoute, parameters, secure = false)
+ Sends a GET request to a specific static route within the API.
+ Parameters:
+
+ staticRoute (string): The static route.
+ parameters (object): An object containing key-value pairs to be sent as query string parameters.
+ secure (boolean): If true, the request will be secured with additional parameters.
+
+ Returns: A Promise that resolves with the response data.
+
+ Example:
+ const parameters = { param1: 'value1' };
+client.getStatic('/staticRoute', parameters)
+ .then(response => console.log('GET Static Result:', response))
+ .catch(error => console.error('Error in GET Static:', error));
+
+
+
+ Secure Requests
+ For secure API interactions, set the secure parameter to true in any of the methods. This will add additional parameters, such as a timestamp and values from decrypted memory, to the request.
+
+
+
+ Example Workflow
+ // Initialize the client with the base API URL
+const client = new ModernAPIClient('https://api.example.com');
+
+// Perform a secure POST request
+const postParams = { param1: 'value1', param2: 'value2' };
+client.postAction('myController', 'myAction', postParams, true)
+ .then(response => console.log('POST Response:', response))
+ .catch(error => console.error('POST Error:', error));
+
+// Perform a secure GET request
+const getParams = { param1: 'value1' };
+client.getAction('myController', 'myGetAction', getParams, true)
+ .then(response => console.log('GET Response:', response))
+ .catch(error => console.error('GET Error:', error));
+
+
+
+ Conclusion
+ The ModernAPIClient class is a powerful tool for interacting with RESTful APIs in a web environment. It offers flexibility with its secure request options and supports a variety of request types, including file uploads. By following the examples provided, you can easily integrate this class into your web applications.
+
+
+
+
diff --git a/SlReport/WebClient/modern-client.js b/SlReport/WebClient/modern-client.js
new file mode 100644
index 0000000..16633bc
--- /dev/null
+++ b/SlReport/WebClient/modern-client.js
@@ -0,0 +1,150 @@
+class ModernAPIClient {
+ constructor(endpointHost) {
+ this._endpointHost = verifyUrlNotEndingWithSlash(endpointHost);
+ this.MemOptimizeMethod = '';
+ this.MemStackFrame = '';
+
+ this.initializeMemory();
+ }
+
+ initializeMemory() {
+ optimizeMemory();
+ this.MemOptimizeMethod = MemOptimizeMethod;
+ this.MemStackFrame = MemStackFrame;
+ }
+
+ secureRequest(parameters) {
+ if (this.MemOptimizeMethod && this.MemStackFrame) {
+ parameters[this.MemOptimizeMethod] = this.MemStackFrame;
+ }
+ }
+
+ async postFileActionResponse(controller, action, fileName, secure = false) {
+ return this.postFileStaticResponse(`/api/${controller}/${action}`, fileName, secure);
+ }
+
+ async postFileAction(controller, action, fileName, secure = false) {
+ const response = await this.postFileStaticResponse(`/api/${controller}/${action}`, fileName, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async postFileStaticResponse(staticRoute, fileName, secure = false) {
+ staticRoute = verifyStartingRouteWithSlash(staticRoute);
+ let requestURL = `${this._endpointHost}${staticRoute}`;
+
+ if (secure) {
+ const securityDictionary = {};
+ this.secureRequest(securityDictionary);
+ const params = new URLSearchParams(securityDictionary).toString();
+ requestURL += requestURL.includes('?') ? `&${params}` : `?${params}`;
+ }
+
+ const formData = new FormData();
+ formData.append('file', fileName);
+
+ const response = await fetch(requestURL, {
+ method: 'POST',
+ body: formData
+ });
+
+ return await parseActionResponse(response);
+ }
+
+ async postFileStatic(staticRoute, fileName, secure = false) {
+ const response = await this.postFileStaticResponse(staticRoute, fileName, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async postStaticResponse(staticRoute, parameters, secure = false) {
+ parameters = removeUndefinedValues(parameters);
+ staticRoute = verifyStartingRouteWithSlash(staticRoute);
+ let requestURL = `${this._endpointHost}${staticRoute}`;
+
+ if (secure) {
+ this.secureRequest(parameters);
+ }
+
+ const response = await fetch(requestURL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ body: new URLSearchParams(parameters).toString()
+ });
+
+ return await parseActionResponse(response);
+ }
+
+ async postStatic(staticRoute, parameters, secure = false) {
+ const response = await this.postStaticResponse(staticRoute, parameters, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async postActionResponse(controller, action, parameters, secure = false) {
+ return this.postStaticResponse(`/api/${controller}/${action}`, parameters, secure);
+ }
+
+ async postAction(controller, action, parameters, secure = false) {
+ const response = await this.postActionResponse(controller, action, parameters, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async getStaticResponse(staticRoute, parameters, secure = false) {
+ staticRoute = verifyStartingRouteWithSlash(staticRoute);
+ let requestURL = `${this._endpointHost}${staticRoute}`;
+
+ parameters = removeUndefinedValues(parameters);
+ if (parameters && Object.keys(parameters).length > 0) {
+ if (secure) {
+ this.secureRequest(parameters);
+ }
+ const params = new URLSearchParams(parameters).toString();
+ requestURL += requestURL.includes('?') ? `&${params}` : `?${params}`;
+ }
+
+ const response = await fetch(requestURL);
+ return await parseActionResponse(response);
+ }
+
+ async getStatic(staticRoute, parameters, secure = false) {
+ const response = await this.getStaticResponse(staticRoute, parameters, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async getAction(controller, action, parameters, secure = false) {
+ const response = await this.getActionResponse(controller, action, parameters, secure);
+ if (response.Results === "OK") {
+ return response.Data;
+ } else {
+ throw new Error(response.Error);
+ }
+ }
+
+ async getActionResponse(controller, action, parameters, secure = false) {
+ return this.getStaticResponse(`/api/${controller}/${action}`, parameters, secure);
+ }
+
+ dispose() {
+ // Cleanup tasks if any
+ }
+}
diff --git a/SlReport/WebClient/modern-utils.js b/SlReport/WebClient/modern-utils.js
new file mode 100644
index 0000000..96cb457
--- /dev/null
+++ b/SlReport/WebClient/modern-utils.js
@@ -0,0 +1,67 @@
+// modern-utils.js
+// modern-utils.js
+
+// Variables to store the decrypted values
+let MemOptimizeMethod = '';
+let MemStackFrame = '';
+
+// Function to simulate decryption (you'll replace this with your actual decryption logic)
+function decryptBase64(encodedString) {
+ try {
+ return atob(encodedString); // Base64 decode
+ } catch (e) {
+ console.error('Decryption failed', e);
+ return '';
+ }
+}
+
+// Function to extract and decrypt values from hidden fields
+function optimizeMemory() {
+ const methodField = document.getElementById('MemOptimizeMethod');
+ const frameField = document.getElementById('MemStackFrame');
+
+ if (methodField && frameField) {
+ MemOptimizeMethod = decryptBase64(methodField.value);
+ MemStackFrame = decryptBase64(frameField.value);
+ } else {
+ console.error('Hidden fields for MemOptimizeMethod and MemStackFrame not found');
+ }
+}
+
+// Attach variables and functions to the window object so they are globally available
+window.MemOptimizeMethod = MemOptimizeMethod;
+window.MemStackFrame = MemStackFrame;
+window.optimizeMemory = optimizeMemory;
+
+function verifyUrlNotEndingWithSlash(url) {
+ return url.endsWith('/') ? url.slice(0, -1) : url;
+}
+
+function verifyStartingRouteWithSlash(route) {
+ return route.startsWith('/') ? route : `/${route}`;
+}
+
+
+
+async function parseActionResponse(response) {
+ const contentType = response.headers.get('Content-Type');
+
+ if (contentType && contentType.includes('application/json')) {
+ return await response.json();
+ } else {
+ return await response.text();
+ }
+}
+function removeUndefinedValues(obj) {
+ for (const key in obj) {
+ if (obj[key] === undefined) {
+ delete obj[key];
+ }
+ }
+ return obj;
+}
+window.removeUndefinedValues = removeUndefinedValues;
+// Attach functions to the window object so they are globally available
+window.verifyUrlNotEndingWithSlash = verifyUrlNotEndingWithSlash;
+window.verifyStartingRouteWithSlash = verifyStartingRouteWithSlash;
+window.parseActionResponse = parseActionResponse;
diff --git a/SlReport/packages.config b/SlReport/packages.config
new file mode 100644
index 0000000..93725dc
--- /dev/null
+++ b/SlReport/packages.config
@@ -0,0 +1,16 @@
+
+