restler.js 4.5 KB
//RESTful API  client 代理

var rest = require('restler');
var URL = require('url');
exports = module.exports = function (logger, settings) {

    var client = {};

    function targetUrl(originUrl) {
        if (settings.proxy && settings.proxy.target && settings.proxy.apiRouteRegexp) {
            return settings.proxy.target + originUrl.substring(settings.proxy.apiRouteRegexp.length);
        } else {
            logger.error('config miss proxy target');
        }
    }

    function getTokens(req) {
        console.log("##@#@", req.session);
        if (req.session.token) {
            var token = {};
            try {
                token = JSON.parse(req.session.token);
            } catch (error) {
                logger.error("token 字符串不能被解析", error);
            }
            return token;
        } else {
            logger.error("401 token不存在");
        }
    }

    function refreshToken(req, res, next, reqOption) {
        var token = getTokens(req);
        var params = {
            'grant_type': 'refresh_token',
            'refresh_token': token.refresh_token
        };
        if (token.tenant && token.tenant.id) {
            params['account'] = token.tenant.id;
        }
        var options = {
            method: 'post',
            data: JSON.stringify(params || {}),
            headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
            timeout: 60 * 1000
        }
        var refreshUrl = settings.proxy.target + settings.proxy.refreshUrl;
        rest.request(refreshUrl, options)
            .on('success', function (data, response) {
                req.session.token = data;
                req.session.save(function (err) {
                    if (err)
                        logger.error(err);
                    else
                        requestAction(reqOption.url, req, res, next)
                })
            })
            .on('fail', function (data, response) {
                logger.error(data);
                res.send({ 'message': '刷新token失败,请重新登陆' });
            })
            .on('error', function (err, response) {
                logger.error(err);
                res.send(err);
            })
            .on('timeout', function (ms) {
                logger.error('timeout', ms);
                res.send({ 'message': '请求超时' });
            });
    }

    function handleSuccess(data, response, req, res, next, reqOption) {
        if (reqOption.url.indexOf(settings.proxy.authUrl) != -1) {
            req.session.token = data;
            req.session.save(function (err) {
                if (err)
                    logger.error(err);
                else
                    res.send(data);
            })
        } else {
            res.send(data);
        }
    }

    function handleFail(data, response, req, res, next, reqOption) {
        if (response.statusCode === 401) {
            refreshToken(req, res, next, reqOption);
        } else {
            res.send(data);
        }
    }

    function getOptions(req) {
        var options = {
            method: req.method.toLowerCase(),
            query: req.query,
            data: JSON.stringify(req.body || {}),
            headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
            timeout: 60 * 1000
        }
        if (req.session.token) {
            var token = getTokens(req);
            options['accessToken'] = token.access_token
        }
        return options;
    }

    function requestAction(url, req, res, next) {
        var options = getOptions(req);
        logger.info('options', options);
        rest.request(url, options)
            .on('success', function (data, response) {
                handleSuccess(data, response, req, res, next, { url, options });
            })
            .on('fail', function (data, response) {
                handleFail(data, response, req, res, next, { url, options });
            })
            .on('error', function (err, response) {
                logger.error(err);
                res.send(err);
            })
            .on('timeout', function (ms) {
                logger.error('timeout', ms);
                res.send({ 'message': '请求超时' });
            });
    }

    client.web = function (req, res, next) {
        var target = targetUrl(req.originalUrl);
        requestAction(target, req, res, next);
    }


    return client;
};


exports['@singleton'] = true;
exports['@require'] = ['igloo/logger', 'igloo/settings'];