Source: request_handler.js

/**
 * This file handles all HTTP Requests to the Server.
 * 
 * @module scripts/request_handler
 */

import PageHandler from "./page_handler.js";

/**
 * Class for handling all HTTP Requests.
 * 
 * @class RequestHandler
 */
class RequestHandler {

    DEFAULT_CONNECTOR = "/";

    THEME_COOKIE_NAME = "theme";

    /**
     * Constructs a new Request Handler.
     * 
     * @constructor
     */
    constructor() {

        this.activeRequests = 0;

        /**
         * Sends an HTTP POST request to the server with a body.
         * 
         * @async
         * @function POST
         * 
         * @param {string} endpoint    - The endpoint you wish to speak to.
         * @param {Array<string>} args - The arguments to add to the URL.
         * @param {object} body        - Either JSON data or a file input to send data.
         * @param {Function} callback  - The callback to call after execution.
         */
        this.POST = async (endpoint, args, body, callback) => {

            this.activeRequests ++;

            endpoint = this.constructEndpoint(endpoint, args);

            let _body = JSON.stringify({ body });
            let headers = { 'Authorization': this.getCookieValue('token') };

            if (body instanceof HTMLInputElement) {

                let formData = new FormData();

                formData.append('file', body.files[0]);
                formData.append('test', 'cringe');

                _body = formData;

            } else {

                headers['Content-Type'] = 'application/json';

            }

            const res = await fetch(endpoint, {

                method: 'POST',
                body: _body,
                headers: headers

            });

            this.activeRequests --;

            callback(await res.json());

        }

        /**
         * Sends an HTTP GET request to the server.
         * 
         * @async
         * @function GET
         * 
         * @param {string} endpoint    - The endpoint you wish to speak to.
         * @param {Array<string>} args - The arguments to add to the URL.
         * @param {Function} callback  - The callback to call after execution.
         */
        this.GET = async (endpoint, args, callback) => {

            this.activeRequests ++;

            endpoint = this.constructEndpoint(endpoint, args);

            const res = await fetch(endpoint, {

                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': this.getCookieValue('token')
                }

            });

            this.activeRequests --;

            callback(await res.json());

        }

        /**
         * Constructs the URL using the endpoint and URL arguments.
         * 
         * @function constructEndpoint
         * 
         * @param {string} endpoint    - The endpoint you wish to speak to.
         * @param {Array<string>} args - The arguments to add to the URL.
         * 
         * @returns {string} The constructed URL.
         */
        this.constructEndpoint = (endpoint, args) => {

            for (let i = 0; i < args.length; i ++) {

                endpoint += this.DEFAULT_CONNECTOR + args[i].toString();

            }

            return endpoint;

        }

        /**
         * Retrieves a certain cookie value from the local storage.
         * 
         * @function getCookieValue
         * 
         * @param {string} name - The name of the variable to look for.
         * 
         * @returns {string} The value of the certain cookie.
         */
        this.getCookieValue = (name) => (
            
            document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''

        )

        /**
         * Set a cookie in the local storage.
         * 
         * @function setCookie
         * 
         * @param {string} name  - The name of the cookie to set.
         * @param {string} value - The value of the cookie.
         */
        this.setCookie = (name, value) => {

            document.cookie = `${name}=${value};`;

        }

        /**
         * Sets the theme in the local storage and updates the page.
         * 
         * @function setTheme
         * 
         * @param {PageHandler} pageHandler  - The handler for UI updates.
         * @param {boolean} changeTheme      - Whether to change the theme or not.
         */
        this.setTheme = (pageHandler, changeTheme=false) => {

            let themeCookie = this.getCookieValue(this.THEME_COOKIE_NAME);
            let themeSet = pageHandler.parseStringToBool(themeCookie);

            let themed = pageHandler.isThemed();

            if (themeCookie == null || themeCookie == '') {

                this.setCookie(this.THEME_COOKIE_NAME, themed);

            }

            if (themed != themeSet) {

                this.setCookie(this.THEME_COOKIE_NAME, !themed);

            }

            if (!changeTheme) return;

            if (!themed) {

                this.setCookie(this.THEME_COOKIE_NAME, true);

            } else {

                this.setCookie(this.THEME_COOKIE_NAME, false);

            }

            pageHandler.changeTheme();

        }

    }

}

export default RequestHandler;