0

HerokuのNode.jsでMemcache使えるようにした

memjsというmemcached clientにpull requestが取り込まれた。

HerokuではアドオンのMemcacheMemcachierを使う事になるが、両方共SASLによる認証が入っている。
SASL認証を使うにはバイナリプロトコルが使えるmemcache clientが必要なのだが、node.jsにはバイナリ使えるのmemjsしか無かったのでとりあえず試したけど認証なしでしか動かなかった。

この時にmemcacheとmemcachierのアドオンを入れたり消したりしてたらmemcachierの中の人からメールが来て、相談してたらOpCode 0x21の時にKeyが必要なところが入ってなかったのを見つけて、修正したらうまく動いたのでpull requestして取り込まれた。
これでNodeでHerokuのMemcacheが使えるようになりました。


memjsの使い方はこんなの。
まだREADMEがしっかり書かれていないのでflagとかが何だかわからないけど、テストコード見たらだいたい使い方もわかってbugfixもできた。

// npm install memjs

var memjs = require('memjs');
var cache = new memjs.Client.create(null, {expires: 10}); // 10sec expire

// set value
cache.set('name', 'shokai', function(err, val){
if(err) console.error('set error');
else{

// get value
cache.get('name', function(err, val, flag){
if(err) console.error('get error');
else console.log('get : '+ (val ? val.toString() : null));
});

// wait 11 sec, then get value
setTimeout(function(){
console.log('wait 3 sec');
cache.get('name', function(err, val, flag){
if(err) console.error('get error');
else console.log('get : '+ (val ? val.toString() : null));
});
}, 11000);
}
});

2バイト以上の文字はencodeURI/decodeURIを通して使う。

0

nvmインストール

MacMiniにnode version managerいれた。

git clone git://github.com/creationix/nvm.git $HOME/.nvm


zshから読み込む
[[ -s $HOME/.nvm/nvm.sh ]] && source $HOME/.nvm/nvm.sh


nvmはbash用で、zshで新しいterminalが開くと
nvm_ls:17: no matches found: vdefault
というエラーがでるけど
alias defaultを設定すればokらしい
nvm alias default v0.6.19

エラー出なくなった。


nodeインストール
nvm install v0.6.19
node -v
npm 1.1.24もついてきた。
あとは普通に使える。tiqav-chatとかbing検索とか動かして試した。


globalオプション付きでnpm installしたモジュールは $HOME/.nvm/バージョン番号/lib/node_modules の中にインストールされてた。


naveはzshで起動した瞬間にterminalが閉じられるのでnvmにした。

0

node.jsでbing.netの画像検索

ちょっと日本語の画像検索使いたかったのと、Node.jsの勉強もしたかったから作った。

デモあり
http://img-search-jp.herokuapp.com/


JSONP APIがある
http://img-search-jp.herokuapp.com/search.json?q=山形&callback=foo


ソースコード
https://github.com/shokai/bing-search-img


bing検索がazureに移動するので8月までしかAPI使えないんだけど、azureのbing web searchのドキュメントがwordファイルしかなかったり、queryのvalueをダブルクオートで囲む珍しい方式だったり、認証方法が書いてなかったり(Basic認証だった)、そもそも組み立てたクエリが正しいのかいまいちわからないので、8月まで旧bing使う。


HerokuのMemcacheがnodeから使えないのつらい・・

0

async.jsで非同期処理をまとめる

複数の非同期処理が両方終わるまで待って結果をまとめて受け取るとか、順番に実行とかできる。


2つHTTPリクエスト同時に使って結果をまとめて受け取る例

var async = require('async');
var request = require('request');

async.parallel(
[function(exit){
request.get('http://shokai.org', function(err, res, body){
if(err) exit('HTTP Request Error');
if(res.statusCode != 200) exit('HTTP Status ('+res.statusCode+')');
exit(null, body);
});
}, function(exit){
request.get('http://masui.sfc.keio.ac.jp', function(err, res, body){
if(err) exit('HTTP Request Error');
if(res.statusCode != 200) exit('HTTP Status ('+res.statusCode+')');
exit(null, body);
});
}], function(err, results){
if(err) throw err;
console.log(results[0].match(/<title>(.+)<\/title>/i)[1]);
console.log(results[1].match(/<title>(.+)<\/title>/i)[1]);
}
);
配列の中に2つのfunctionが入っていて、両者でexitという名前で使っている第一引数がエラー、第二引数が結果のコールバックを呼ぶとasync.parallelの第二匹数に指定した関数にまとまる。

parallelの他にseriesとwaterfallがある。


実行結果

shokai.org - 橋本商会
Masui Lab.


参考

0

画像を安全に埋め込みたい

チャットに画像のURLが貼られた時に、安全にimgタグを埋め込みたいという議論があったので書いておく。

一番単純な実装だと、

var s = "はろー http://shokai.org.ex/example.jpg てすとてすと";
s.replace(/(https?:\/\/.+)\.(jpe?g|gif|png)/g, "<img src=\"$1.$2\">$1.$2</img>");
のようにすると
"はろー <img src="http://shokai.org.ex/example.jpg">http://shokai.org.ex/example.jpg</img> てすとてすと"

になるのだが、よく考えると http://tumblr.com/logout#.png みたいなのを貼られるとimgタグが描画された瞬間にログアウトしてしまう。

正規表現がショボいのも悪いけど、最近はURL末尾に画像の拡張子が付いていなくても画像が返ってくるサービスもある。そういうのが埋め込めない。

問題

いくつか問題というか解決策がある。どれが正しいのかは知らない。
  1. GETでアクセスしただけでログアウトしてしまうサービスが悪い
  2. imgタグを描画する前に、本当にURLがimageなのか調べるべき。でもJavaScriptだけではcontent-type調べられない。
  3. ブラウザはサーバーに期待するmime-typeを付けてリクエストする。imgタグからリクエストするなら X-Mime-Condition: image/* とか
3が一番いいけど、2が現実的かな。


api.geta6.net

2について、geta6が2つ作ってくれた。

http://api.geta6.com/imagent
URL先のページや画像をPhantomJS+xvfbでキャプチャして画像で返してくれるAPIで、これを使うとなんでもimgタグに埋め込んで大丈夫になる。
画像だったら画像がそのまま返ってくるし、webページも画像になって返ってくる。
resizeやcropもできる。

http://api.geta6.com/headers
URLを渡すとmime-typeがJSONPで取得できるので、JavaScriptで判別してimg/embed/audio/iframe/aなど適当なタグで埋め込む。


content-type.herokuapp.com


Node.jsの勉強がてら、簡単なのを作ってみた。
http://content-type.herokuapp.com/


http://content-type.herokuapp.com/type/image/IMAGE_URL のようにすると、typeがimageでなければ埋め込まれない。
<img src="http://content-type.herokuapp.com/type/image/http://twiticon.herokuapp.com/shokai/bigger">


画像じゃない時はエラー画像が表示される。
<img src="http://content-type.herokuapp.com/type/image/http://tumblr.com/logout#.png">

あと、 http://content-type.herokuapp.com/type/http://twiticon.herokuapp.com/shokai でmime-typeが取得できるのでこれを使って適当にタグを埋め込むJSライブラリを作ると便利かもしれない。

Herokuのmemcache

上のをNodeで作ってて誤算だったのは、HerokuのNode.jsではMemcacheが使えなかったことだった。
HerokuのMemcacheはSASLという認証が必要なんだけど、SASLをサポートしているNode.jsのmemcacheライブラリがmemjsしかない。でもmemjsもSASL通らなかった。

しょうがないのでmemory-cacheというオンメモリキャッシュを使った。