一个短信服务的需求,决定用Nodejs来写,本来是要用 nodejs 的 soap 的服务,可是node-soap 这个包貌似有坑,总是报错,也许是我的版本有问题,我用的是 v0.8.7,后来只能通过抓包,向 SOAP 的接口发送 HTTP 的 POST 请求了,最后终于还是实现了。 主要的功能是实现一个短信服务的接口,外部的发送 http 请求到这个短信服务接口上来,短信服务向发送短信的服务器端转发请求,相当于一个中间验证和请求服务。 主要用到了 Nodejs 的 mysql 包node-mysql,还有 nodejs 解析 XML 的包libxmljs。虽然是一个小的脚本,代码也比较蹩脚(我的 JS 基础很差),但是写完还是学会了不少东西,比如 nodejs 操作 mysql,发送 post 请求,MD5 加密。。。这里加简单的注释贴出来,忘各位看官多指正,第一次写 nodejs!!

var url = require('url');
var http = require('http');
var qstr = require('querystring');
var mysql = require('mysql');
var libxmljs = require('libxmljs');

var connection = mysql.createConnection({
    //建立数据库连接
    host: '127.0.0.1',
    user: 'root',
    password: 'yuansir-web',
    database: 'test',
    port: '3306'
});

var userName = 'yuanxuxu.com';
var passWord = 'yuanxuxu.com';

//创建一个服务器
http.createServer(function(req, res) {
    //解析url中的参数
    var queryString = url.parse(req.url).query;
    var phone = qstr.parse(queryString)['phone'];
    var content = qstr.parse(queryString)['content'];
    var account = qstr.parse(queryString)['account'];
    var password = qstr.parse(queryString)['password'];

    if (
        phone == undefined ||
        content == undefined ||
        account == undefined ||
        password == undefined
    ) {
        res.write('-6');
        res.end();
        return false;
    }

    phones = phone.split(',');
    phonesLength = phones.length;

    if (phonesLength > 5000) {
        res.write('-7');
        res.end();
        return false;
    }

    for (i = 0; i < phonesLength; i++) {
        if (!isMobile(phones[i])) {
            res.write('-3');
            res.end();
            return false;
        }
    }
    //下面是数据库查询,很简单
    connection.query(
        'SELECT * FROM userlist WHERE username = ? AND password = ? LIMIT 1',
        [account, md5(password)],
        function(err, results) {
            if (err === null && typeof results[0] != 'undefined') {
                var timestmp = new Date().getTime();
                sendSms(userName, passWord, content, phone, timestmp, res);
            } else {
                res.write('-1');
                res.end();
                return false;
            }
        }
    );
}).listen(3000);

function isMobile(vStr) {
    var vReg = /^1(3|4|5|8)\d{9}$/;
    return vReg.test(vStr);
}

function md5(str) {
    var hash = require('crypto').createHash('md5'); //这是nodejs的MD5加密,用crypto的包
    return hash.update(str).digest('hex');
}

function sendSms(
    userName,
    passWord,
    smsContent,
    cellPhone,
    sendAppId,
    httpRes
) {
    var body =
        '<?xml version="1.0" encoding="UTF-8"?>\
                        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://service.techown.com/"><SOAP-ENV:Body><ns1:massSend><userName>' +
        userName +
        '</userName><passWord>' +
        passWord +
        '</passWord><smsContent>' +
        smsContent +
        '</smsContent><cellPhone>' +
        cellPhone +
        '</cellPhone><sendTime></sendTime><smsPriority></smsPriority><sendAppId>' +
        sendAppId +
        '</sendAppId></ns1:massSend></SOAP-ENV:Body></SOAP-ENV:Envelope>';

    //HTTP请求参数
    var options = {
        hostname: 'xxxxxxxxxx',
        port: xxxx,
        path: '/SMSService/webService/sms',
        method: 'POST',
        headers: {
            Connection: 'Keep-Alive',
            'User-Agent': 'PHP-SOAP/5.3.13',
            'Content-Type': 'text/xml; charset=utf-8',
            SOAPAction: '',
            'Content-Length': body.length
        }
    };

    var req = http.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function(chunk) {
            if (res.statusCode == '200') {
                //HTTP相应的status
                var xmlDoc = libxmljs.parseXml(chunk); //解析HTTP响应的body
                //chunk 中含有html实体,这里多做1次解析
                var massSend = xmlDoc.get('//massSend');
                var xmlDoc2 = libxmljs.parseXml(massSend.text());
                var sendStatus = xmlDoc2.get('//replyCode').text();
                // var timestmp = new Date().getTime();
                var empplog = {
                    phone: cellPhone,
                    content: smsContent,
                    status: sendStatus
                };
                var query = connection.query(
                    'INSERT INTO empplog SET ?',
                    empplog,
                    function(err, result) {
                        if (err) throw err;
                    }
                );
                if (sendStatus == '001') {
                    httpRes.write('1');
                    httpRes.end();
                } else {
                    httpRes.write('-8');
                    httpRes.end();
                }
            }
        });
    });

    req.on('error', function(e) {
        //throw e.message;
    });

    // write data to request body
    req.write(body);
    req.end();
}

利用

nohup node test.js &

来启动脚本作为后台守护进程

来启动脚本作为后台守护进程 但是这里我用了forever,用 npm 安装

sudo npm install forever -g

然后用 forever 让 nodejs 应用后台执行,forever 可以分别记录输出和错误日志,可以在 js 中作为 api 使用

forever start test.js

具体的 forever 的使用请去 git 上查看。

转载请注明: 转载自Ryan 是菜鸟 | LNMP 技术栈笔记

如果觉得本篇文章对您十分有益,何不 打赏一下

谢谢打赏

本文链接地址: Nodejs 初试(建立 http 服务,mysql,post 请求,解析 XML)

知识共享许可协议 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可