node.js覚書系メモ

自メモ)
多分他の人にはあんま役に立たないと思う

のほうがいいかも

環境構築編は

バージョン変えればほとんどそのまま使えますね

標準ぽくないプラグインとかの話は別に分けました


自分のはexpressのメモだけど、こんなのもあるらしい


1>例外キャッチ

hogeServer.js

//〜 いろんな処理 〜


process.on('uncaughtException', function (error) {
    console.error('uncaughtException: ' + error.stack);
    process.exit(); //node.jsのプロセスを落とす
});

これは下記みたいな形で監視シェルで=>プロセス再立上げ前提ならありかな

crontab -e

 */1 * * * * /home/XXX/watch.sh 2>&1 >> /home/XXX/watch.log

とか登録しておく流れ

/home/XXX/watch.sh

#!/bin/sh
nodefile=hogeServer.js
ROOT=/home/XXX/node/hoge

date=`date`
ALIVE=`ps -ef | grep $nodefile | grep -v grep | wc -l`
if [ ${ALIVE} = 0 ]; then
        # 監視プロセスがなくなった
        line="$ROOT/sv_hoge.sh"
        echo "[$date ]<reboot>line=$line"
        result=`$line`
        echo "[$date ]<reboot>result=$result"
        exit 0;
else   
        # 監視プロセスが生存中
        exit 1;
fi

/home/XXX/node/hoge/sv_hoge.sh

ROOT=/home/XXXX/node/hoge
nodefile=hogeServer.js
/bin/kill -9 `/bin/ps aux | /bin/grep -e $nodefile| /usr/bin/awk '{print $2}'`

cd $ROOT
/usr/local/bin/node $ROOT/$nodefile 2>&1 >> /dev/null&
#/usr/local/bin/node $ROOT/$nodefile 2>&1 >> ./sv_hoge.log &


備考)

var db  = require('hogeDB');
var cl = db.con();

process.on('uncaughtException', function (error) {
    console.error('uncaughtException: ' + error.stack);

	//☆ ここが悩みポイント ><
	if(cl==null || !cl.connected){
		dbg.log('====[/uncaughtException] reconect_db====');
                if(cl !=null)cl.end(); //コネクション閉じる
		cl = db.con(); //再接続
		if(cl==null || !cl.connected){
			process.exit();
		}
		return;
	}
}

この方式だと現在うまく動かせてないです。。。

cl.connected
の状態がうまく取れないみたい。。うーん。
プロセス落とす前提ってもんにょりしちゃうんですけどね。。(汗




2>シェルを叩いてみる系のリクエスト

hogeServer.js

//〜 いろんな処理 〜

var exec = require('child_process').exec;
app.get('/bals',function(req, res) {
    console.log('===bals===');
	var resopnse = {status: 'success',
                    message:'bals'};
	res.send(resopnse);
	exec('/home/XXXX/node/hoge/sv_hoge.sh');
});

ココらへんとかは実際basic認証とか必要だよね(苦笑




3> express系の設定

事前に


npm install express


最初これでよくはまってた

  • node_modules/setting.js
exports.host = "127.0.0.1";
exports.port = "1234";
var express = require('express'), ejs = require('ejs');

var setting = require('setting');

app.configure(function (){
    app.use(parted({
        path: __dirname + '/tmp',
        multiple:true
    }));
    app.enable('jsonp callback');
    app.register('.ejs', ejs);
    app.set('view options', { layout: false });
    app.set('views', __dirname + '/views');   //☆1
    app.use(express.static(__dirname + '/public'));//☆2

    app.set('view engine', 'ejs');
    app.use(express.bodyParser());
    app.use(express.logger());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.errorHandler({ //☆3
         dumpExceptions: true,
         showStack: true
    }));
});


// 〜中略〜


app.listen(setting.port, setting.host);

静的コンテンツ置く記述が//☆2


/hoge/public/
images
javascripts
stylesheets
に置いて

/hoge/views/index.ejs

var arr = [];
arr[0] = '/images/hoge_one.png';
arr[1] = '/images/hoge_two.png';

と参照と。
ココらへんめんどいから
httpでアクセス記載してるコードもちらほら見たりする
(jqueryのJSとか)

☆3は ejsでのエラーをPlayみたいに表示させたい場合に設定する。
普段だとコンソールに吐かれるだけなので・・(汗


ちなみに
外部公開するときは exports.host が

  • 外からアクセス可能なIPにするか
  • node proxy等をかますか

どちらかになる感じです。


4> post/get両対応のアクションをする記述オレオレ版

app.get('/hoge',function(req, res) {hoge(req, res,'get');});
app.post('/hoge',function(req, res) {hoge(req, res,'post');});

function hoge(req, res,mode) {
    var udid = mode=='post' ? req.body.id:req.query.id;
    dbg.log('====== /hoge :' + udid);

    if (!udid) {
      	//res.writeHeader(404, {'Content-Type': 'text/json'});
   	//res.end("internal error");	
	// や
	//res.send(null, 404);
	//とかの記述も可能
		
	var resopnse = {status: 'error',
               message: 'Bad Request'};
        res.send(resopnse);
    	return;
    }

ココらへんはIOS側との兼ね合いで
実装の人がどっちがいいかの好みになるんだよね〜*1

IOSに人的にはJSONよりXML(正確にはdictonary形式)がいいらしいし。。
まあ難しい問題ではありますな。。


5> DBの接続 と DBの値の JSON形式戻り値形式のお手抜き方法

事前に


npm install mysql

mysqlで hogeDB/hogeTable
作成済みの前提で下記

  • node_module/hogeDB.js
var mysql   = require('mysql');
var setting   = require('setting');//  node_module/setting.js 等で設定情報を外出し

exports.con = function() {
    var client = mysql.createClient({
        user: setting.user,
        password: setting.pass
    });
    client.query('use hogeDB;'); //使うデータベースの指定
    return client;
}

exports.getMember = function(client,id,callback) {
    dbg.log("==getMember:"+id);
    
    //[TODO] 'select * from hogeTable where id =' + id +' ;' , とかみたいにも書けますね
    var q = client.query('select * from hogeTable where id =? ;'[id],
        function(error, results, fields) {
        if (error){
		dbg.log("[getMember]error="+error);
		if (callback)callback(null);	
		return null;
	}
	if (callback)callback(results);
        return results;
    });
	dbg.log("[getMember]q ="+q.sql);
}

var db  = require('hogeDB');
var cl = db.con();

app.get('/member', function(req, res) {

	var id = req.query.id;

	//☆ ここが悩みポイント ><
	if(cl==null || !cl.connected){
		dbg.log('====[/member] reconect_db====');
                if(cl !=null)cl.end(); //コネクション閉じる
		cl = db.con(); //再接続
		if(cl==null || !cl.connected){
			process.exit();
		}
		return;
	}

	db.getMember(cl,id,function(user) {
		var response = JSON.stringify(user, null, "    "); //DBの中身をJSONで返してくれる手抜き関数
        	res.send(response);
	});


で☆の悩みポイントは
PHPでもMySQLとの(ソケット)コネクションが切れる問題があり
=>
node v6までは上記で動いていたわけなんですけど
たまに動かない状況が v7以降から発生

毎回
 db.con & cl.end() すればいいんじゃね?
という奴も見るんですが、実際どうなんですかね??
<若干遅くなる(瞬間ロックかかる)気がする・・



6> ファイルのダウンロード/アップロード

ダウンロードは結構シンプル

var path ='upload/hoge.dat';
res.download(path);


アップロードはこんなイメージですかね・・

var fs = require('fs'),
    path = require('path');

exports.upload = function(src, dst, callback) {

    console.log("upload:src="+src+",dst="+dst);

    if( path.existsSync(src) && fs.statSync(src).isFile() ) {
        var srcFile = fs.createReadStream(src);
        var dstFile = fs.createWriteStream(dst);

        srcFile.addListener("data", function(chunk) {
            dstFile.write(chunk);
        });

        srcFile.addListener("close",function() {
            dstFile.end();
            if(callback)callback();
        });
	return; 
   } 
   console.log('not found a file : ' + src);
}
	upload(req.body.data, 'upload/hoge.dat',function() {
		callback(null);
	});


Android側からは

File file = new File();

//〜略〜
HttpPost httpPost = new HttpPost(url_upload);
MultipartEntity entity = new MultipartEntity();
entity.addPart("udid",new StringBody(udid));
entity.addPart("data", new FileBody(file) );
httpPost.setEntity(entity);

なイメージになるかと。
ただイタズラでポンポンファイルUpとかされるとかに備えて
セッションキーとかパラメータに入れるんですかねー。実際の運用面だと(汗



7> sha1暗号化

【Node.js】cryptを使って共通鍵暗号方式の使い方 | creator note
上記のリンクだと複合化まで記載あるみたいだけどいるんですかね?
実際にはsha1のキーまで投げてしまって文字比較したほうが楽な気がする。。(アプリ固有データ文字列とか混ぜて)

var crypto = require('crypto');
exports.sha1 = function(data) {
    return crypto.createHash('sha1').update(data).digest('hex');
}

*1:IOS開発の人のほうが発言権強いので<汗