Ejemplo n.º 1
0
de.Block.Expr.prototype._run = function(params, context) {
    var promise = new no.Promise();

    promise.resolve( new de.Result.Value( this.expr(params, context) ) );

    return promise;
};
Ejemplo n.º 2
0
            res.on('end', function() {
                result.end();

                if (status >= 400 && status <= 599) {
                    context.error(full_path + 'error ' + status);

                    var mime = de.mime( res.headers );

                    var body;
                    if ( mime === 'application/json' ) {
                        try {
                            body = JSON.parse( result.buffer );
                        } catch ( e ) {
                            body = 'JSON.parse: Cannot parse response body';
                        }
                    }

                    return promise.reject( de.error({
                        'id': 'HTTP_' + status,
                        'message': http_.STATUS_CODES[status],
                        'body': body
                    }) );

                } else {
                    promise.resolve(result);
                }
            });
Ejemplo n.º 3
0
 .done(function(result) {
     if ( result instanceof de.Result ) {
         promise.resolve(result);
     } else {
         promise.resolve( new de.Result.Raw(result, options.data_type, options.output_type) );
     }
 })
Ejemplo n.º 4
0
    (function run() {
        if (i < l) {
            workers = [];

            var group = groups[i];
            for (var j = 0, m = group.length; j < m; j++) {
                (function(item) {
                    var worker = item.block.run(params, context)
                        .done(function(r) {
                            results[item.index] = r;
                        });

                    workers.push(worker);
                })( group[j] );
            }

            i++;

            wait = no.Promise.wait(workers).done(run);

        } else {
            workers = null;

            promise.resolve( that._getResult(results) );
        }
    })();
Ejemplo n.º 5
0
de.Block.Http.prototype._run = function(params, context) {
    var url = this.url(params, context);

    var options = this.options;

    var query = (options.extend) ? params : null;

    var headers = null;
    if (options.proxy && context.request) {
        var req_headers = context.request.headers;

        //  Копируем все http-заголовки, кроме тех, которые указаны в disallow_headers.
        headers = {};
        for (var header in req_headers) {
            if (!disallow_headers[header]) {
                headers[header] = req_headers[header];
            }
        }
    }

    if (options.headers) {
        headers = no.extend(headers || {}, options.headers);
    }

    var promise = new no.Promise();

    var httpPromise = de.http(
        {
            url: url,
            method: options.method,
            headers: headers,
            max_redirects: options.max_redirects,
            only_status: options.only_status,
            http_options: options.http_options
        },
        query,
        context
    )
        .done(function(result) {
            if ( result instanceof de.Result ) {
                promise.resolve(result);
            } else {
                promise.resolve( new de.Result.Raw(result, options.data_type, options.output_type) );
            }
        })
        .fail(function(error) {
            promise.reject(error);
        });

    promise.forward('abort', httpPromise);

    return promise;
};
Ejemplo n.º 6
0
 req.on('error', function(error) {
     context.error(full_path + 'error ' + error.message);
     promise.reject( de.error({
         'id': 'HTTP_UNKNOWN_ERROR',
         'message': error.message
     }) );
 });
Ejemplo n.º 7
0
 res.on('close', function(error) {
     context.error(full_path + 'error ' + error.message);
     promise.reject( de.error({
         'id': 'HTTP_CONNECTION_CLOSED',
         'message': error.message
     }) );
 });
Ejemplo n.º 8
0
de.Block.Include.prototype._run = function(params, context) {
    var promise = new no.Promise();

    var filename = this.resolveFilename( this.filename(params, context) );

    var options = no.extend({}, this.options, {dirname: path_.dirname(filename)});

    var including = _includes[filename];
    if (!including) {
        including = _includes[filename] = new no.Promise();

        de.file.eval(filename, 'de', de.sandbox, context)
            .done(function(include) {
                including.resolve(include);
            })
            .fail(function(error) {
                _includes[filename] = null;

                including.reject(error);
            });
    }

    including
        .done(function(include) {
            var block = de.Block.compile(include, options);

            de.forward( block.run(params, context), promise );
        })
        .fail(function(error) {
            promise.resolve(error);
        });

    return promise;
};
Ejemplo n.º 9
0
de.Block.Http.prototype._run = function(params, context) {
    var url = this.url(params, context);

    var options = this.options;

    var query = (options.extend) ? params : null;

    var headers;
    if (options.proxy && context.request) {
        var req_headers = context.request.headers;

        //  Копируем все http-заголовки, кроме тех, которые указаны в disallow_headers.
        headers = {};
        for (var header in req_headers) {
            if (!disallow_headers[header]) {
                headers[header] = req_headers[header];
            }
        };
    } else {
        headers = null;
    }

    var promise = new no.Promise();

    de.http.get(url, query, headers, context)
        .done(function(result) {
            promise.resolve( new de.Result.Raw(result, options.data_type, options.output_type) );
        })
        .fail(function(error) {
            promise.reject(error);
        });

    return promise;
};
Ejemplo n.º 10
0
    running.done(function(result) {
        //  Возможность положить что-нибудь в state после выполнения блока.
        var select = options.select;
        if (select) {
            var state = context.state;
            var obj = result.object();

            for (var key in select) {
                //  FIXME: Сигнатура?!
                state[key] = select[key](obj, context);
            }
        }

        if (options.after) {
            options.after(params, context, result);
        }

        if (options.result) {
            result = new de.Result.Value( options.result( result.object(), context, params ) );
        }

        if ( options.template && !(result instanceof de.Result.Error) ) {
            var filename = that.resolveFilename( options.template(params, context) );

            de.file.eval(filename, 'de', de.sandbox, context)
                .done(function(template) {
                    var t1 = Date.now();
                    var r = template( result.object() );
                    context.log_end('info', '[template ' + JSON.stringify(filename) + '] ended', t1);

                    /*
                    if (data && typeof data === 'object') {
                        if ( Array.isArray(data) ) {
                            return new de.Result.Array(data);
                        } else {
                            return new de.Result.Object(data);
                        }
                    }
                    */
                    if (typeof r === 'string') {
                        promise.resolve( new de.Result.HTML(r) );
                    } else if (r instanceof de.Result) {
                        promise.resolve(r);
                    } else {
                        //  FIXME: Что тогда?
                    }
                })
                .fail(function(error) {
                    promise.resolve(error);
                });
        } else {
            promise.resolve(result);
        }

    });
Ejemplo n.º 11
0
de.Block.Call.prototype._run = function(params, context) {
    var module = this.module;
    var method = this.method;

    if (module) {
        var call = module[method] || module;
        try {
            return call(params, context, method);
        } catch (e) {
            return no.Promise.resolved( de.error({
                id: 'MODULE_CALL',
                message: e.message
            }) );
        }
    } else {
        return no.Promise.resolved( de.error({
            id: 'MODULE_NOT_FOUND',
            message: 'Cannot find module "' + this.moduleName + '"'
        }) );
    }
};
Ejemplo n.º 12
0
                .done(function(template) {
                    var t1 = Date.now();
                    var r = template( result.object() );
                    context.log_end('info', '[template ' + JSON.stringify(filename) + '] ended', t1);

                    /*
                    if (data && typeof data === 'object') {
                        if ( Array.isArray(data) ) {
                            return new de.Result.Array(data);
                        } else {
                            return new de.Result.Object(data);
                        }
                    }
                    */
                    if (typeof r === 'string') {
                        promise.resolve( new de.Result.HTML(r) );
                    } else if (r instanceof de.Result) {
                        promise.resolve(r);
                    } else {
                        //  FIXME: Что тогда?
                    }
                })
Ejemplo n.º 13
0
de.Block.Function.prototype._run = function(params, context) {
    var result;
    try {
        result = this.func(params, context);
    } catch (e) {
        return no.Promise.resolved( de.error({
            id: 'FUNC_CALL',
            message: e.message
        }) );
    }

    var block = de.Block.compile( result, { dirname: this.options.dirname } );

    return block.run(params, context);
};
Ejemplo n.º 14
0
de.Block.File.prototype._run = function(params, context) {
    var filename = this.resolveFilename( this.filename(params, context) );

    var options = this.options;

    var promise = new no.Promise();

    de.file.get(filename, context)
        .done(function(result) {
            promise.resolve( new de.Result.Raw(result, options.data_type, options.output_type) );
        })
        .fail(function(error) {
            promise.resolve(error);
        });

    return promise;
};
Ejemplo n.º 15
0
    promise.on('abort', function() {
        //  Останавливаем run(), чтобы он не запускал больше ничего.
        i = l;

        promise.resolve( de.error({
            id: 'ERROR_ABORTED'
        }) );


        if (workers) {
            //  FIXME: Нужно ли это?
            wait.reject();

            for (var j = 0, m = workers.length; j < m; j++) {
                workers[j].trigger('abort');
            }
        }
    });
Ejemplo n.º 16
0
 .done(function(result) {
     promise.resolve( new de.Result.Raw(result, options.data_type, options.output_type) );
 })
Ejemplo n.º 17
0
de.Block.Array.prototype._run = function(params, context) {
    var promise = new no.Promise();

    var that = this;

    var results = [];
    var groups = this.groups;

    var i = 0;
    var l = groups.length;

    var workers;
    var wait;

    promise.on('abort', function() {
        //  Останавливаем run(), чтобы он не запускал больше ничего.
        i = l;

        promise.resolve( de.error({
            id: 'ERROR_ABORTED'
        }) );


        if (workers) {
            //  FIXME: Нужно ли это?
            wait.reject();

            for (var j = 0, m = workers.length; j < m; j++) {
                workers[j].trigger('abort');
            }
        }
    });

    (function run() {
        if (i < l) {
            workers = [];

            var group = groups[i];
            for (var j = 0, m = group.length; j < m; j++) {
                (function(item) {
                    var worker = item.block.run(params, context)
                        .done(function(r) {
                            results[item.index] = r;
                        });

                    workers.push(worker);
                })( group[j] );
            }

            i++;

            wait = no.Promise.wait(workers).done(run);

        } else {
            workers = null;

            promise.resolve( that._getResult(results) );
        }
    })();

    return promise;
};
Ejemplo n.º 18
0
de.Block.Value.prototype._run = function(params, context) {
    return no.Promise.resolved(this.value);
};
Ejemplo n.º 19
0
 .fail(function(error) {
     promise.resolve(error);
 });
Ejemplo n.º 20
0
de.http = function(options, params, context) {
    var parsed = url_.parse(options.url, true, true);

    parsed = no.extend(parsed, options.http_options);

    if (params) {
        parsed.query = no.extend(parsed.query || {}, params);
    }

    var max_redirects = ( options.max_redirects === undefined ) ? 3 : options.max_redirects;
    var only_status = options.only_status;

    parsed.headers = options.headers;
    parsed.method = options.method;

    var req;
    var promise = new no.Promise();

    promise.on('abort', function() {
        req.abort();
    });

    var full_path = '[http ' + url_.format(parsed) + '] ';
    var http_status = 0;
    var received_length = 0;

    var t1 = Date.now();
    promise.done(function() {
        context.log_end('info', full_path + http_status + ' ' + received_length + ' ended', t1);
    });
    promise.fail(function() {
        context.log_end('info', full_path + http_status + ' failed', t1);
    });

    doHttp(parsed, 0);

    return promise;

    function doHttp(options, count) {
        var post_data;
        if (options.method === 'post') {
            var headers = options.headers || (( options.headers = {} ));

            if ('application/json' === headers['Content-Type']) {
                post_data = JSON.stringify(options.query);
            } else {
                post_data = qs_.stringify(options.query);
            }

            if (post_data) {
                //  FIXME: Если никаких данных не передается, то, кажется,
                //  эти заголовки и не нужны вовсе?
                //
                if (!headers['Content-Type']) {
                    headers['Content-Type'] = 'application/x-www-form-urlencoded';
                }
                headers['Content-Length'] = post_data.length;
            }

        } else {
            options.path = url_.format({
                pathname: options.pathname,
                query: options.query
            });
        }

        req = ( (options.protocol === 'https:') ? https_ : http_).request(options, function(res) {
            var status = res.statusCode;

            if (only_status) {
                //  FIXME: Непонятно, нужно ли это?
                //  Но если там длинная дата, то ждать ее нет смысла.
                req.abort();

                return promise.resolve( new de.Result.Value({
                    status: status,
                    headers: res.headers
                }) );
            }

            http_status = status;

            var error;
            if (status === 301 || status === 302) {
                //  TODO: Кэшировать 301 запросы.

                //  FIXME: А это нельзя вынести повыше?
                res.resume();

                var location = res.headers['location'] || '';

                // FIXME: MAX_REDIRECTS.
                if (count >= max_redirects) {
                    context.error('Too many redirects');
                    return promise.reject( de.error({
                        'id': 'HTTP_TOO_MANY_REDIRECTS',
                        'status': status,
                        'location': location
                    }) );
                }

                location = url_.resolve(options.href, location);
                options = url_.parse(location, true, true);

                context.info(full_path + 'redirected to ' + location);

                return doHttp(options, count + 1);
            }

            var result = new de.Result.Http(res.headers);

            res.on('data', function(data) {
                received_length += data.length;
                result.data(data);
            });
            res.on('end', function() {
                result.end();

                if (status >= 400 && status <= 599) {
                    context.error(full_path + 'error ' + status);

                    var mime = de.mime( res.headers );

                    var body;
                    if ( mime === 'application/json' ) {
                        try {
                            body = JSON.parse( result.buffer );
                        } catch ( e ) {
                            body = 'JSON.parse: Cannot parse response body';
                        }
                    }

                    return promise.reject( de.error({
                        'id': 'HTTP_' + status,
                        'message': http_.STATUS_CODES[status],
                        'body': body
                    }) );

                } else {
                    promise.resolve(result);
                }
            });
            res.on('close', function(error) {
                context.error(full_path + 'error ' + error.message);
                promise.reject( de.error({
                    'id': 'HTTP_CONNECTION_CLOSED',
                    'message': error.message
                }) );
            });
        });

        req.on('error', function(error) {
            context.error(full_path + 'error ' + error.message);
            promise.reject( de.error({
                'id': 'HTTP_UNKNOWN_ERROR',
                'message': error.message
            }) );
        });

        if (post_data) {
            req.write(post_data);
        }
        req.end();
    }

};
Ejemplo n.º 21
0
 .fail(function(error) {
     promise.reject(error);
 });
Ejemplo n.º 22
0
        req = ( (options.protocol === 'https:') ? https_ : http_).request(options, function(res) {
            var status = res.statusCode;

            if (only_status) {
                //  FIXME: Непонятно, нужно ли это?
                //  Но если там длинная дата, то ждать ее нет смысла.
                req.abort();

                return promise.resolve( new de.Result.Value({
                    status: status,
                    headers: res.headers
                }) );
            }

            http_status = status;

            var error;
            if (status === 301 || status === 302) {
                //  TODO: Кэшировать 301 запросы.

                //  FIXME: А это нельзя вынести повыше?
                res.resume();

                var location = res.headers['location'] || '';

                // FIXME: MAX_REDIRECTS.
                if (count >= max_redirects) {
                    context.error('Too many redirects');
                    return promise.reject( de.error({
                        'id': 'HTTP_TOO_MANY_REDIRECTS',
                        'status': status,
                        'location': location
                    }) );
                }

                location = url_.resolve(options.href, location);
                options = url_.parse(location, true, true);

                context.info(full_path + 'redirected to ' + location);

                return doHttp(options, count + 1);
            }

            var result = new de.Result.Http(res.headers);

            res.on('data', function(data) {
                received_length += data.length;
                result.data(data);
            });
            res.on('end', function() {
                result.end();

                if (status >= 400 && status <= 599) {
                    context.error(full_path + 'error ' + status);

                    var mime = de.mime( res.headers );

                    var body;
                    if ( mime === 'application/json' ) {
                        try {
                            body = JSON.parse( result.buffer );
                        } catch ( e ) {
                            body = 'JSON.parse: Cannot parse response body';
                        }
                    }

                    return promise.reject( de.error({
                        'id': 'HTTP_' + status,
                        'message': http_.STATUS_CODES[status],
                        'body': body
                    }) );

                } else {
                    promise.resolve(result);
                }
            });
            res.on('close', function(error) {
                context.error(full_path + 'error ' + error.message);
                promise.reject( de.error({
                    'id': 'HTTP_CONNECTION_CLOSED',
                    'message': error.message
                }) );
            });
        });
Ejemplo n.º 23
0
de.Block.prototype.run = function(params, context) {
    context = context || new de.Context(params);

    var promise = new no.Promise();

    var that = this;

    var t1 = Date.now();
    promise.done(function() {
        that.log_end(context, 'ended', t1);
    /*
        //  См. pull request #57.
        promise.done(function(result) {
            var result_log = (result && result instanceof de.Result) ? ('[' + JSON.stringify(result.object()) + '] ') : '';
            that.log_end(context, result_log + 'ended', t1);
    */
    });

    var options = this.options;

    //  Проверяем гвард, если он есть.
    if ( options.guard && !options.guard(params, context) ) {
        return promise.resolve( new de.Result.Value(null) );
    }

    if (options.before) {
        options.before(params, context);
    }

    var running;

    //  Смотрим, определен ли ключ для этого блока.
    var key;
    if (options.key) {
        //  Вычисляем ключ.
        key = options.key(params, context);

        //  Смотрим, не закэширован ли блок с таким же ключом.
        var cached = _results[key];
        if (cached) {
            //  Не протух ли еще наш кэш?
            if (cached.timestamp + options.maxage > context.now) {
                //  Нет, берем из кэша promise с результатом.
                running = cached.promise;
                context.debug('[found in cache key=' + key + ']');
            } else {
                //  Протух. Выкидываем из кэша.
                //  FIXME: Может тут таки нужно делать delete.
                _results[key] = null;
            }
        }
    }

    if (!running) {
        //  Если блок все-таки не закэширован, запускаем его.
        var _params = (options.params) ? options.params(params, context) : params;
        var _context;
        if (options.local) {
            _context = context.clone();
            _context.state = {};
        } else {
            _context = context;
        }
        var running = this._run(_params, _context);

        //  Если определен таймаут для блока.
        if (options.timeout) {
            var hTimeout = null;

            //  Если блок выполнился быстрее, чем таймаут.
            running.always(function() {
                if (hTimeout) {
                    //  Отменяем setTimeout.
                    clearTimeout(hTimeout);
                    hTimeout = null;
                }
            });

            hTimeout = setTimeout(function() {
                //  Если через options.timeout ms ничего не случится, кидаем ошибку.
                context.error(that.debug_id() + ' timeout');
                running.reject( de.error({
                    id: 'TIMEOUT',
                    message: 'Timeout' // FIXME: Вменяемый текст.
                }) );

                //  И отменяем все запросы этого блока.
                //  Пока что отменяются только http-запросы.
                running.trigger('abort');

            }, options.timeout);
        }

        //  Кэша нет, но ключ есть.
        if (key) {
            //  Кэшируем блок на будущее.
            //  Можно не ждать окончания выполнения блока, т.к. там все равно promise кэшируется.
            _results[key] = {
                timestamp: context.now,
                promise: running
            };

            running.fail(function() {
                //  Если выполнение привело к ошибке, выкидываем ключ из кэша.
                //  Чтобы в следующий раз блок выполнился еще раз.
                //  FIXME: Может лучше использовать delete?
                _results[key] = null;
            });
        }
    }

    var that = this;

    running.done(function(result) {
        //  Возможность положить что-нибудь в state после выполнения блока.
        var select = options.select;
        if (select) {
            var state = context.state;

            de.log.warn('You are using deprecated `select` section of the block options. It will dissapear soon. Use `state` instead.');

            var obj = result.object();

            for (var key in select) {
                //  FIXME: Сигнатура?!
                state[key] = select[key](obj, context);
            }
        }

        if (options.state) {
            var patch = options.state(result.object(), context, params);
            context.state = de.mergeObjects(context.state, patch);
        }

        if (options.after) {
            options.after(params, context, result);
        }

        if (options.result) {
            result = new de.Result.Value( options.result( result.object(), context, params ) );
        }

        if ( options.template && !(result instanceof de.Result.Error) ) {
            var filename = that.resolveFilename( options.template(params, context) );

            de.file.eval(filename, 'de', de.sandbox, context)
                .done(function(template) {
                    var t1 = Date.now();
                    var r = template( result.object() );
                    context.log_end('info', '[template ' + JSON.stringify(filename) + '] ended', t1);

                    /*
                    if (data && typeof data === 'object') {
                        if ( Array.isArray(data) ) {
                            return new de.Result.Array(data);
                        } else {
                            return new de.Result.Object(data);
                        }
                    }
                    */
                    if (typeof r === 'string') {
                        promise.resolve( new de.Result.HTML(r) );
                    } else if (r instanceof de.Result) {
                        promise.resolve(r);
                    } else {
                        //  FIXME: Что тогда?
                    }
                })
                .fail(function(error) {
                    promise.resolve(error);
                });
        } else {
            promise.resolve(result);
        }

    });

    running.fail(function(error) {
        promise.resolve(error);
    });

    return promise;
};