betajs/betajs-server

View on GitHub
src/ajax/ajax.js

Summary

Maintainability
A
3 hrs
Test Coverage
Scoped.define("module:Ajax.NodeAjax", [
    "base:Ajax.Support",
    "base:Net.Uri",
    "base:Net.HttpHeader",
    "base:Promise",
    "base:Objs",
    "base:Types"
], function (AjaxSupport, Uri, HttpHeader, Promise, Objs, Types) {
    
    var Module = {
        
        supports: function (options) {
            return true;
        },
        
        execute: function (options) {
            var uri = Uri.appendUriParams(options.uri, options.query || {});
            if (options.method === "GET")
                uri = Uri.appendUriParams(uri, options.data || {});
            var parsed = Uri.parse(uri);
            var opts = {
                  method: options.method,
                  host: parsed.host,
                  port: parsed.port,
                  path: parsed.path + (parsed.query ? "?" + parsed.query : "")
              };
            opts.headers = {};
            if (parsed.user || parsed.password) {
                opts.headers.Authorization = 'Basic ' + Buffer.from(parsed.user + ':' + parsed.password).toString('base64');
            } else if (options.bearer) {
                opts.headers.Authorization = 'Bearer ' + options.bearer;
            }
            var post_data = null;
            var form = null;
            if (options.method !== "GET" && !Types.is_empty(options.data)) {
                var FS = require("fs"); 
                Objs.iter(options.data, function (value) {
                    if (!form && (value instanceof FS.ReadStream))
                        form = new (require('form-data'))();
                });
                if (form) {
                    Objs.iter(options.data, function (value, key) {
                        form.append(key, value);
                    });
                } else if (options.contentType === "json") {
                    if (options.sendContentType)
                        opts.headers["Content-Type"] = "application/json;charset=UTF-8";
                    post_data = JSON.stringify(options.data);
                } else {
                    if (options.sendContentType)
                        opts.headers["Content-type"] = "application/x-www-form-urlencoded";
                    post_data = Uri.encodeUriParams(options.data, undefined, true);
                }
                if (post_data)
                    opts.headers['Content-Length'] = post_data.length;
              }

            var promise = Promise.create();

            if (options.cookies)
                opts.headers.Cookie = Uri.encodeUriParams(options.cookies);
            
            if (form)
                opts.headers = Objs.extend(opts.headers, form.getHeaders());

            var headerPromise = form ? Promise.create() : Promise.value(true);
            if (form) {
                form.getLength(function (err, len) {
                    if (!err) {
                        opts.headers['Content-Length'] = len;
                        headerPromise.asyncSuccess(true);
                    } else
                        headerPromise.asyncError(err);
                });
            }

            headerPromise.forwardError(promise).success(function () {
                var request = require(parsed.protocol === "https" ? "https" : "http").request(opts, function (result) {
                    var data = "";
                    if (options.decodeType === "raw")
                        result.setEncoding("binary");
                    result.on("data", function (chunk) {
                        data += chunk;
                    }).on("end", function () {
                        if (HttpHeader.isSuccessStatus(result.statusCode)) {
                            // TODO: Figure out response type.
                            AjaxSupport.promiseReturnData(promise, options, data, options.decodeType || "json");
                        } else {
                            AjaxSupport.promiseRequestException(promise, result.statusCode, result.statusText, data, options.decodeType || "json");
                        }
                    });
                });
                if (options.timeout) {
                    request.on('socket', function(socket) {
                        socket.removeAllListeners('timeout');
                        socket.setTimeout(options.timeout, function() {});
                        socket.on('timeout', function() {
                            request.abort();
                        });
                    }).on('timeout', function() {
                        AjaxSupport.promiseTimeoutException(promise);
                        request.abort();
                    });
                }
                if (form)
                    form.pipe(request);
                else {
                    if (post_data && post_data.length > 0)
                        request.write(post_data);
                    request.end();
                }
            });
            return promise;
        }
            
    };
    
    AjaxSupport.register(Module, 10);
    
    return Module;
});