@AppKu/StashKu

@AppKu/StashKu

v1.0.46

source

node/http-request-loader.js

import qs from 'qs';
import url from 'url';
import path from 'path';
import Filter from '../filter.js';
import ModelUtility from '../modeling/model-utility.js';
import DeleteRequest from '../requests/delete-request.js';
import GetRequest from '../requests/get-request.js';
import OptionsRequest from '../requests/options-request.js';
import PatchRequest from '../requests/patch-request.js';
import PostRequest from '../requests/post-request.js';
import PutRequest from '../requests/put-request.js';

function bodyParse(req) {
    if (Buffer.isBuffer(req.body)) {
        return JSON.parse(req.body.toString());
    } else if (typeof req.body === 'string') {
        return JSON.parse(req.body);
    }
    return req.body;
}

/**
 * Attempts to parse a request object from an `http.IncomingMessage`, matched by the request method.
 * @param {http.IncomingMessage} httpReq - The request object.
 * @param {Modeling.AnyModelType} [modelType] - Optional model set 
 * @returns {Promise.<GetRequest | PostRequest | PutRequest | PatchRequest | DeleteRequest | OptionsRequest>}
 */
async function HttpRequestLoader(httpReq, modelType) {
    let method = httpReq.method.toLowerCase();
    let req = null;
    let resource = null;
    let url = new URL(httpReq.url, 'http://localhost');
    if (modelType) {
        resource = ModelUtility.resource(modelType, method);
    } else if (url.pathname) {
        resource = path.basename(url.pathname);
    }
    if (method === 'get') {
        req = new GetRequest().from(resource);
        if (url.search) {
            let clone = qs.parse(url.search.substring(1));
            if (!modelType && clone.from) {
                req.from(clone.from);
            }
            if (clone.count) {
                req.metadata.count = !!clone.count;
            }
            if (clone.distinct) {
                req.metadata.distinct = !!clone.distinct;
            }
            if (clone.headers) {
                req.headers(clone.headers);
            }
            if (clone.properties && clone.properties.length) {
                req.properties(...clone.properties);
            }
            if (clone.skip) {
                req.metadata.skip = clone.skip;
            }
            if (clone.sorts && clone.sorts.length) {
                req.sort(...clone.sorts);
            }
            if (clone.take) {
                req.metadata.take = clone.take;
            }
            if (clone.filter && !clone.where) { //support legacy where/filters
                clone.where = clone.filter;
            }
            if (typeof clone.where === 'string') {
                req.where(new Filter(JSON.parse(clone.where)));
            } else {
                req.where(Filter.fromObject(clone.where));
            }
        }
    } else if (method === 'post') {
        req = new PostRequest().to(resource);
        let clone = bodyParse(httpReq);
        if (!modelType && clone.to) {
            req.to(clone.to);
        }
        if (clone.count) {
            req.metadata.count = !!clone.count;
        }
        if (clone.headers) {
            req.headers(clone.headers);
        }
        if (clone.objects && clone.objects.length) {
            if (modelType) { //convert objects to model type
                for (let i = 0; i < clone.objects.length; i++) {
                    clone.objects[i] = Object.assign(new modelType(), clone.objects[i]);
                }
            }
            req.objects(...clone.objects);
        }
    } else if (method === 'put') {
        req = new PutRequest().to(resource);
        let clone = bodyParse(httpReq);
        if (!modelType && clone.to) {
            req.to(clone.to);
        }
        if (clone.count) {
            req.metadata.count = !!clone.count;
        }
        if (clone.headers) {
            req.headers(clone.headers);
        }
        if (clone.pk && clone.pk.length) {
            req.pk(...clone.pk);
        }
        if (clone.objects && clone.objects.length) {
            if (modelType) { //convert objects to model type
                for (let i = 0; i < clone.objects.length; i++) {
                    clone.objects[i] = Object.assign(new modelType(), clone.objects[i]);
                }
            }
            req.objects(...clone.objects);
        }
    } else if (method === 'patch') {
        req = new PatchRequest().to(resource);
        let clone = bodyParse(httpReq);
        if (!modelType && clone.to) {
            req.to(clone.to);
        }
        if (clone.count) {
            req.metadata.count = !!clone.count;
        }
        if (clone.all) {
            req.metadata.all = !!clone.all;
        }
        if (clone.headers) {
            req.headers(clone.headers);
        }
        if (clone.template) {
            req.template(clone.template);
        }
        if (typeof clone.where === 'string') {
            req.where(new Filter(JSON.parse(clone.where)));
        } else {
            req.where(Filter.fromObject(clone.where));
        }
    } else if (method === 'delete') {
        req = new DeleteRequest().from(resource);
        let clone = bodyParse(httpReq);
        if (!modelType && clone.from) {
            req.from(clone.from);
        }
        if (clone.count) {
            req.metadata.count = !!clone.count;
        }
        if (clone.all) {
            req.metadata.all = !!clone.all;
        }
        if (clone.headers) {
            req.headers(clone.headers);
        }
        if (typeof clone.where === 'string') {
            req.where(new Filter(JSON.parse(clone.where)));
        } else {
            req.where(Filter.fromObject(clone.where));
        }
    } else if (method === 'options') {
        req = new OptionsRequest().from(resource);
        let clone = bodyParse(httpReq);
        if (!modelType && clone.from) {
            req.from(clone.from);
        }
        if (clone.headers) {
            req.headers(clone.headers);
        }
    }
    return req;
}

export default HttpRequestLoader;