NodeJS 做中间服务器

in 编程
关注公众号【好便宜】( ID:haopianyi222 ),领红包啦~
阿里云,国内最大的云服务商,注册就送数千元优惠券:https://t.cn/AiQe5A0g
腾讯云,良心云,价格优惠: https://t.cn/AieHwwKl
搬瓦工,CN2 GIA 优质线路,搭梯子、海外建站推荐: https://t.cn/AieHwfX9

NodeJS 做中间服务器

实现前后端分离

node 天生适合处理业务层面的逻辑,但是不适合作为数据计算处理。在做web项目的时候,使用 node 来做中间服务器,处理客户端的页面渲染,转发请求到接口服务器,实现前后端的分离,后端不再需要管理前端的业务渲染,专注于接口的抽象化和灵活化,前端不再需要等待路由页面的添加才能写页面,可以自己往路由添加需要的页面。

共同管理

中间服务器的功能非常简单,因此前后端可以共同管理,前端负责添加页面层级的路由,后端负责转发到接口服务器的路由

淘宝基于 Node 的前后端分离


上图是淘宝基于Node的前后端分离分层,以及Node的职责范围。简单解释下:

node + express 构建中间服务器

server.js

var express = require('express')
var rMiddle = require('./router/rMiddle.js')

// remoteapi 开头的转发给接口服务器
app.use('/remoteapi', rMiddle);

// 前端页面渲染
app.get('/index', function(req, res) {
    res.sendFile(__dirname + 'index.html');
})

app.listen('8080', function(err) {
    if (err) {
        return;
    }
    console.log('Listening at localhost:8080');
});

/router/rMiddle.js

var express = require('express');
var http = require('http');
var querystring = require('querystring');
var router = express.Router();

// 你的接口服务器地址
var connectServer = {
    port: '9000',
    protocol: 'http://',
    host: '192.168.0.1'
};
var serverDomainPort = connectServer.port;
var serverDomainProtocol = connectServer.protocol;
var serverDomainHost = connectServer.host
var serverDomain = serverDomainProtocol + serverDomainHost + ':' + serverDomainPort;

// 定义一个通用 Get 接口,转接所有数据,不再一个个写
router.get('*', (req, res) => {
    let reqUrl = serverDomain + req.url;
    console.log('[GET Request]: ', reqUrl);
    http.get(reqUrl, (sres) => {
        var statusCode = sres.statusCode;
        var contentType = sres.headers['content-type'];

        let error;
        if (statusCode !== 200) {
            error = new Error(`Request Failed.\n` + `Status Code: ${statusCode}`);
        } else if (!/^application\/json/.test(contentType)) {
            error = new Error(`Invalid content-type.\n` + `Expected application/json but received ${contentType}`);
        }
        if (error) {
            // consume response data to free up memory
            sres.resume();
            res.status(500).end();
            return;
        }

        sres.setEncoding('utf8');
        let rawData = '';
        sres.on('data', (chunk) => rawData += chunk);
        sres.on('end', () => {
            try {
                let parsedData = JSON.parse(rawData);
                res.json(parsedData);

            } catch (e) {
                res.status(500).send(e.message);
            }
        });
    }).on('error', (e) => {
        console.log(`Got error: ${e.message}`);
        res.status(500).end();
    });  
})

// 定义一个通用的 Post 接口,转接所有数据
router.post('*', (req, res) => {
    var reqUrl = serverDomain + req.url;
    var reqContentType = req.headers['content-type'];
    var reqBody = req.body;
    // 根据 请求的 content-type 判断用哪种格式化方式
    var reqData = reqContentType.indexOf('json') !== -1 ? JSON.stringify(reqBody) : querystring.stringify(reqBody);
    var postOpt = {
        host: serverDomainHost,
        port: serverDomainPort,
        path: req.url,
        method: 'POST',
        headers: {
            'Content-Type': reqContentType
        }
    };
    var sreq = http.request(postOpt, (sres) => {
        var body = '';
        var error;
        if (sres.statusCode !== 200) {
            error = new Error(`Request Failed.\n` + `Status Code: ${sres.statusCode}`)
        }
        if (error) {
            console.log(error.message);
            sres.resume();
            res.status(500).end();
            return;
        }
        sres.on('data', (data) => {
            body += data;
        })
        .on('end', () => {
            try {
                var parsedData = JSON.parse(body);
                res.json(parsedData);
            } catch (e) {
                console.log(e.message);
                res.status(500).send(e.message);
            }
        })
        .on('error', () => {
            console.log('[ERROR] when req url:', reqUrl, reqData);
            res.status(500).send('error');
        })
    })
    sreq.write(reqData);
    sreq.end();
})

module.exports = router;

透传还是不透传

中间服务器在转发请求的时候,如果只是单纯的请求数据,那么透传是很好的方法,但是如果想做进一步的优化,可能就需要中间层做一定的处理。

其他资源

关注公众号【好便宜】( ID:haopianyi222 ),领红包啦~
阿里云,国内最大的云服务商,注册就送数千元优惠券:https://t.cn/AiQe5A0g
腾讯云,良心云,价格优惠: https://t.cn/AieHwwKl
搬瓦工,CN2 GIA 优质线路,搭梯子、海外建站推荐: https://t.cn/AieHwfX9
扫一扫关注公众号添加购物返利助手,领红包
Comments are closed.

推荐使用阿里云服务器

超多优惠券

服务器最低一折,一年不到100!

朕已阅去看看