Node クックブック - izudon/izudon.github.io GitHub Wiki
- 6章 Express で開発をスピードアップ
express
- 5章 Websocket を使って Ajax を超える
websocket
-
socket.io
サーバからクライアントの(またはその逆)メソッドを呼び出せる。- 'コールバック' という。
-
now
Nowjs コールバックを一段と簡単にした。 socket.io-client
- 4章 データベース接続
-
ya-csv
CSVファイル -
mysql
MySQL -
mongodb
MongoDB -
mongoskin
mongodb
のスーパーセット -
cradle
CouchDB - ACID をサポート。- CouchDB は REST API 準拠なので http.request で全部できなくもない。
- MongoDB も 4.0 からトランザクション(ACID 特性)をサポートした。
-
redis
Redis - メモリ内に収まる程度のデータの場合、最適な選択肢。 -
hiredis
Cで書いたredis
。Redis 提供。redis
よりも高速。
-
- 3章 データのシリアル化
- JSON は
JSON.dtringify()
JSON.parse()
がビルトインされている。 -
xml2js
XMLファイル・データを扱う -
colors
色をつけやすくする
- JSON は
- 2章 HTTPオブジェクトをより深く
connect
formidable
- 1章 Webサーバを立てる
-
http
- HTTP サーバや HTTP 接続を構築したりする場合 -
path
- パスのベースネームを取得したりする場合など -
fs
- ファイルシステムのファイルを利用する場合 -
url
- クエリストリングを取り出す場合など -
querystring
- ポストデータを連想記憶配列化する場合など
-
$ sudo npm install -g formidable
<form method="post" enntype="multipart/form-data">
<input type="file" name="userfile1"><br>
<input type="file" name="userfile1"><br>
<input type="submit">
</form>
- PHP では
$_POST['fieldname']
を使える。- POST データを
$_POST[]
に格納するまでブロッキングされているため。
- POST データを
- Node ではどうやるかはすべて開発者に委ねられている。
-
querystring
モジュール-
querystring.parse( postData )
でポストデータを連想記憶配列化できる。
-
-
util
モジュール-
util.inspect(postDataObject)
で、オブジェクトをJSON形式で出力。
-
$ sudo npm install -g connect
-
connect
モジュールによるサーバの生成- メソッドチェーンで様々な設定をつなぎ、
最後にコールバック関数をチェーンする。
- メソッドチェーンで様々な設定をつなぎ、
var app = connect()
.use( connect.bodyParser() )
.use( connect.limit('64kb') )
.use( function( req, res ){
;
}
Node はミニマリストアプローチのため堅牢さは実装者に大きく依存する(!!)。
-
path.noemalize()
- パスの正規化により 相対ディレクトリ攻撃 と ヌルバイト攻撃 を
回避しようとするもの。- 相対ディレクトリ攻撃
http://server.name/../../../../../passwd
- ヌルバイト攻撃
http://server.name/secure.js%00/index.html
- 相対ディレクトリ攻撃
- パスの正規化により 相対ディレクトリ攻撃 と ヌルバイト攻撃 を
-
path.basename()
- ベースネームのみ取得(前回までのコード)= 比較的安全
- 請求できるファイル名をこちらから限定してしまう。
- キャッシュ機能を備えた、成熟したモジュール。
- RFC2616(HTTP 1.1)準拠。
データをディスクから全部読み込んでしまうのではなく
response
に pipe することができる。
-
fs.createReadStream()
<- readStresm オブジェクトを返す。 -
fs.createReadStream().on( 'open', function(){ ... } );
- オープン時にイベントハンドラを仕掛ける。
-
fs.createReadStream().once( 'open', function(){ ... } );
- オープン時に1度しか使わない処理なので .once() で仕掛ける。
- イベントが発生してイベントハンドラの実行が終わり次第イベントリスナは解放。
-
fs.createReadStream().once( 'error', function( e ){ ... } );
- エラーハンドラを仕掛けられる。
-
stream.pipe( response )
- これでフローを制御しながら延々とやっておいてくれる。
-
readStream
クラス-
EventEmitter
クラスを継承 - -> 豊富なイベントハンドラ
-
-
readStream
クラス-
inputStream
クラスの子クラス? - ->
pipe()
メソッドでoutputStream
にパイプできる?
-
-
stream.on( 'data', function( data ){ ... } );
-
data
イベントは、ディスクから1チャンクデータを取得するたびに呼ばれる。
1チャンクのデフォルトは 64KB。
-
- Buffer クラス
- インスタンス生成時にサイズ指定してまとまった大きさのメモリを確保できる。
変数の代わりにここに今回は溜めこんでる。 - ここでは
stat()
したときのstats.size
つまりファイルサイズ分の
領域をあらかじめ確保し、data
イベント毎に1チャンク分を足していってる。 - -> あまりにも大きいファイルがあると領域確保失敗の恐れ。
(バッファオーバーフロー:次項で対策)
- インスタンス生成時にサイズ指定してまとまった大きさのメモリを確保できる。
- キャッシュをもうクラスとして実装しちゃった。
- サイズ上限を決めそれ以下のファイルのみキャッシュすることにした。
- JavaScript の変数は関数スコープ。
- ブロックスコープではない!
- 中途半端な場所に現れた変数宣言(
var s;
等)はすべて
関数冒頭に引っ張り上げられて解釈される。 - 書籍『インタラクティブ・データビジュアライゼーション』に書いてあった。
- スクリプト内変数に情報を貯めておけば、次のセッションでも使いまわせる。
-
Date.now()
で現在日時、
fs.stat()
でファイル最終更新日時等(ctime, mtime, atime)が取得できる。
- fs モジュール
- ファイルシステムのファイルを扱うモジュール。
-
fs.exists( <pathname>, function( exists ){ ... } );
-
<pathname>
のファイルが存在するか調べる。 - 相対パス指定の起点はスクリプト(
server.js
)の実行ディレクトリ。 - 存在すれば
true
存在しなければfalse
を引数に入れて
コールバック関数を呼び出す。
-
-
fs.readFile( <pathname>, function( err, data ){ ... } );
-
<pathname>
のファイルを読み込み、コールバック関数を呼ぶ。 -
err
なんらかのエラーがあればtrue
が格納。 -
data
読み込んだデータが格納。
-
- decodeURI()
-
%20
などを解釈してデコードする
-
- http モジュール
- HTTP リクエストとレスポンスを処理する。
-
http.createServer( function( request, response ){ ... } ).listen(8080);
- HTTP サーバプロセスを作成し、ポート 8080番 を開いて接続を待つ。
- 具体的な処理はコールバック関数の中に。
-
request.url
- リクエストのURLが格納されてくる。
-
response.writeHead( 200, { 'Content-Type': 'text/html' } )
- ステータスコード 200 番で応答を作成。
- Content-Type などその他もろもろのヘッダ情報は第2引数のハッシュに指定。
-
response.end( 'Wahoo!' )
- 'Wahoo!' と出力してレスポンスを終える。
response.finished
がtrue
になる。
- 'Wahoo!' と出力してレスポンスを終える。
- path モジュール
- path.baseneme() でベースネームを取り出せる。
-
path.basename( '/foo/bar/baz.html' )
->baz.html
-
path.basename( '/foo/bar/baz.html', '.html' )
->baz
- url モジュール
- クエリストリングを取り出せる。
url.parse( decodeURL( request.url ), true ).query.id