X-Powered-By:Express
Expressで作ったサイトを動かすとレスポンスヘッダに
X-Powered-By:Express
こんなのつきます。
俺のサイトはNodeだぜ フフンみたいな人はいいんですがいつか脆弱性がみつかったときにしめしめって思われるのもなんだか怖いので消すようにしました。
Express3系ならこんな感じで簡単に消せます。
var app = express(); app.disable('x-powered-by');
Express2系の人はres.removeHeaderを使えばシンプルに消せます。
こんなミドルウェア作ってルーティングミドルウェアの呼出し前に差し込みすればいい感じかと。
app.use(function (req, res, next) { res.removeHeader("x-powered-by"); next(); });
ちなみにこれが実装されてるところはこの辺(express3.2)
https://github.com/visionmedia/express/blob/3.2.0/lib/application.js#L48
app.defaultConfiguration = function(){ // default settings this.enable('x-powered-by'); // <-初期値設定 this.set('env', process.env.NODE_ENV || 'development'); this.set('subdomain offset', 2); debug('booting in %s mode', this.get('env')); // implicit middleware this.use(connect.query()); this.use(middleware.init(this)); // <- ここで実設定 ...
https://github.com/visionmedia/express/blob/3.2.0/lib/middleware.js#L21
exports.init = function(app){ return function expressInit(req, res, next){ req.app = res.app = app; if (app.enabled('x-powered-by')) { res.setHeader('X-Powered-By', 'Express'); // <-ここ } req.res = res; res.req = req; req.next = next; req.__proto__ = app.request; res.__proto__ = app.response; res.locals = res.locals || utils.locals(res); next(); } };
こんな感じで書かれてるのでapp.disabledでやればきえるってすぐわかってよいですね。
Nodeのファイルスコープ
Nodeのファイルスコープについて
JSでスコープを有するものは静的なものでfunction, block、動的スコープではcatch, withとそこそこありますが通常の処理系ではファイルスコープなんてものはないです。
でもNodeではファイル内でvarと宣言した変数はrequireしてもとくにグローバルに漏れずに見かけ上ファイルスコープがあるみたいになってます。
最初これには「おっ?」っておもったんですが、これはこんな感じの実装で実現されてます。
https://github.com/joyent/node/blob/master/src/node.js
NativeModule.getSource = function(id) { return NativeModule._source[id]; } NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', '\n});' ]; NativeModule.prototype.compile = function() { var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); var fn = runInThisContext(source, this.filename, 0, true); fn(this.exports, NativeModule.require, this, this.filename); this.loaded = true; };
NativeModule.prototype.compileが走るとファイル内のソース文字列を取得(getSource)して無名関数でラップして実行(runInThisContext)されてます。
NativeModule.wrap = function(script) { // ここでラップしてる return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ //こいつでラップされてる。 '(function (exports, require, module, __filename, __dirname) { ', '\n});' ];
ここでrequireとかmoduleとか__filenameとか__dirnameを渡してるのでファイル内ではこれらの情報にまるでグローバル変数にアクセスするかのように親オブジェクトの指定なしにアクセスできるようになってます。
ドキュメントもよく読んでみるとそれっぽいこと書いてますね。
http://nodejs.jp/nodejs.org_ja/api/globals.html#globals_global_objects
Global Objects
これらのオブジェクトは全てのモジュールで有効です。 これらのオブジェクトのいくつかは実際はグローバルスコープではなくモジュールスコープです - 注意してください。
exports#
現在のモジュールの全てのインスタンス間で共有されるオブジェクトで、 require を通じてアクセス可能になります。 exports は module.exports と同じオブジェクトです。 exports は実際はグローバルではなく、各モジュール毎のローカルです。
require()#
{Function}
require モジュールを指します。モジュール の節を参照してください。 require は実際はグローバルではなく、各モジュール毎のローカルです。
module#
{Object}
現在のモジュールへの参照です。 特に module.exports は exports オブジェクトと同じです。 module は実際はグローバルではなく、各モジュール毎のローカルです。
...
JSのルールを壊さない良い実装だと思います。 :)
大きなPubSub、小さなPubSub。
JavaScriptにおいてもそのほかの言語においても疎結合というのは結構大きなテーマの一つだと思います。
そんな疎結合を促す実装としてPubSubがにわかに脚光をあびてますね。
にわかというより定期的に盛り上がってる気がしますが。
僕はあまりデザインパターン厨ではないのであまり語れるようなことはないのですが疎結合なコードというのはコードの再利用性が高まり幸せ度がかなり高いものだと思います。
そんなPubSubを強力に後押しするライブラリは世の中星の数ほどあるわけですが、ほんの少しだけ融通が利かないなーって思うこともあって半年くらい前に自作しました。 そう、95%くらい車輪の再発明です。
その名もPubsubJS(https://github.com/nazomikan/PubsubJS)。 どこかですごく似た名前を聞いたことはあるわけですがまぁそのへんはおいといて何がいっぱいあるPubSubライブラリで不満だったのか、そしてそれをどんなアプローチで解消したのか。
たくさんのコードを書いてて非常に気になったのはSubscriberがPublisherになり得るという事実です。
少し迂回しますが、世の中ではjQueryのおかげかCommonJSの仕様のおかげか、はたまたあの翻訳記事のおかげか、Promiseがはやりましたね。
Promiseは何を解決したのか。
Promiseがもたらしたパラダイムシフトは非同期な(イベント)処理をあたかも同期的に書いてるかのように書けるというところだと思います。
非同期な処理をあたかも同期的に書いてるかのように書けることがなぜ幸せかというとその処理のトリガーを引いたスコープで続きの処理が書けるからです。 (ほかにもいろいろあるとは思いますが。)
例えばよくある商品検索サイトでお気に入りに何かを追加したりするような処理について考えてみましょう。
すごい適当にかいてますが☆がお気に入り追加ボタンだったとしましょう。
ajax成功時に☆を★に変えたりクラスを少し変えたりしてますね。
こういうのってthenコールバックが処理トリガーをひいたそのスコープでかけるからevt.currentTarget(クリックされたお気に入りアイコンの要素)とかにアクセスできて実現できるんですよね。
これがもし`Favorite.prototype.add`の$.ajaxのプロパティの中でsuccessプロパティを用意してそこにコールバックをかかなければならなかったとしたらevent.currentTargetにアクセスする方法はありませんね。
※こういう場合
Favorite.prototype.add = function (itemId) { return $.ajax({ type: "POST", url: "/echo/json/", data: { json: itemId, delay: 1 }, success: function () { // ここじゃ呼出し元のスコープのevent.currentTargetにアクセスできない } }); };
かといってこのスコープでevent.currentTargetにアクセスするためにその要素を引き回すというのも、かなり依存性を強めるナンセンスな手段でしょう。
とまぁこんな悩みを解決してくれるわけです。
これは非常に有益で常にこの恩恵をうけたいものです。
では話を戻してPubSubへ。
今のようなアプリケーションをPubSubを使って実装するとこんな感じになるでしょう。
お気に入りアイコンがクリックされたことをpublishして、お気に入りがそれをsubscribeしてるので通知を受けて動くという感じです。
お互いがお互いのことを意識していない非常に疎結合な実装ですがさきほどPromiseが解決していた点がまた問題としてあがってきます。
そう、Subscriber側では当然元のスコープの変数にアクセスできません。
あらかじめいっておくとこういう問題はそもそもPub/Subモデルが解決しようとしている問題ではないので、これが単純なPub/Subで解決できないのは非常に当たり前のことです。
Promiseは元のスコープに対してpromiseオブジェクトを返却することでその問題を解決してましたが、これは呼出し元と呼び出される側が返り値をやりとりするというとても疎結合とは呼べない処理の結びつきを生んでしまっています。
Pub/Subはこの結びつきをなくすかわりにPromiseのような柔軟な非同期処理の記述方法を失っています。
これはトレードオフ以外の何者でもなくどちらを責めるわけにもいかないでしょう。
ただ僕にとって、この二つを同時に必要と思うことがあるのもまた一つの真実だったのです。
この問題を整理して考えると、本質的には”SubscriberもPublisherに転じることがある”という風にまとめられると思います。
つまりどういうことかというと先ほどのアプリケーションでいえば、PublisherはItemList、SubscriberはFavoriteという関係でしたがお気に入り追加処理を終えたときにSubscriberであるはずのFavoriteがこんどはPublisherだったItemListに対して完了したことを通知したいという事情が発生してるわけです。
今回作ったPubsubJSはこの辺をうまく解決してくれるあれです。
で、どういう風に解決したかというと
大きなPubSub、小さなPubSubを作ることで解決しました。
大きなPubSub?
小さなPubSub?
よくわかりませんね。
pubsubというはイベントの中央管理者です。
いくつものオブジェクト間でイベントをやりとりするためにそれぞれのイベントを一重に管理している管理者です。
それとは別に小さなpubsub(Pubsub#Context)を作りました。
これはコードをみる方が早いでしょう。
先ほどのアプリケーションをPubsubJSの小さなpubsubで作るとこんな感じで表現できます。
注目すべき点はこことそこです。
ここ
ItemList.prototype.addFavorite = function (evt) { var target = $(evt.currentTarget), itemId = target.data('itemId'), localContext = pubsub.Context.create(); localContext.subscribe('favorite.added', function () { alert('favorite added'); target.text('★'); target.removeClass('selectable'); }); pubsub.publish('favorite.icon.clicked', localContext, itemId); };
そこ
Favorite.prototype.add = function (context, itemId) { $.ajax({ type: "POST", url: "/echo/json/", data: { json: itemId, delay: 1 } }).then(function () { context.publish('favorite.added'); }); };
問題が解決しましたね。
全体的なイベントを管理するpubsubとPublisher-Subscriber間での小さなイベント管理者pubsub#Contextという二人の管理者をつくることで元のスコープ内でSubscriberがPublisherに転じたときに通知されるsubscriberを書くことができて問題が解決します。
この小さな管理者もまた、pubsubの実装に従っているため、このイベントが引かれることを絶対としていない疎結合な関係にあります。
とまぁこんな感じで僕の場合は幸せな日々がおくれるようになりました。
以上ステマでした。
蛇足(補足)。
知人からコールバックじゃあかんのん?っていわれたので回答。
SubscriberがPublisherに転じたときに起こすイベントの数だけコールバック渡すのあまり現実的じゃなかったりsubscribeしてる全てのメソッドにも自分の処理と関係ないコールバック渡されるの嫌じゃないですか。
たとえばコールバックだとこんなの
function p1() { var handler1 = function..., handler2 = function ...; pubsub.publish('p1.executed', handler1, handler2); } pubsub.subscribe('p1.executed', function a(handler1, handler2) { //...こっちでは特定の何かが終わった時にhandler1を実行する }); pubsub.subscribe('p1.executed', function b(handler1, handler2) { //...こっちでは特定の何かが終わった時にhandler2を実行する });
こういうのってaが自分と関係ないhandlerを、bが自分と関係ないhandler2を渡されるの嫌じゃないですか。
さらにそれぞれ別個に渡せるようにするってなるとそれって依存性すごいじゃないですか
というので小さなイベントの管理者を渡すのがよいなとおもって実装した所存です。
あと、大きなpubsubに名前ルールきめてlocalContext作ってるところもpubsubにpublishしたらええやんともいわれたのでその辺もフォロー
いいたいことは多分こんな感じだと思います。
function p1() { pubsub.subscribe('local.a.executed', function () { //... }); pubsub.publish('p1.executed', handler1, handler2); } pubsub.subscribe('p1.executed', function a() { // something to do pubsub.publish('local.a.executed'); });
こうしちゃうとリスナがずっとpubsubに残っちゃってリソース勿体ない(pubsub#Contextで小さなpubsubを作る場合、その小さなpubsubがGCに回収されるときリスナも解放される)であったり、p1が実行されるたびにlocal.a.executedのsubscriberが一個ずつふえていってバグりますね。
結構致命的だと思います。
そもそもの話、大きなサイト作ってりゃ名前ルールで縛るのも限界がきてそんな細かいイベントまで管理していると実装が破綻するっていう話もあると思います。
なので私は小さry
Nodeでプライベートな(exportsされてない)メソッドのテスト
だいたいこの記事のまんまですが大雑把な訳記事だと思ってください。
こんなファイル(app.js)があったとする。
//app.js exports.testableMethod = function () { complicatedMethod(untestableMethod); }; var untestableMethod = function (a, b) { return (a + b); };
testableMethodはexportsされてるのでテストできますね(まぁ参照エラーでるけど)
こういう時untestableMethodのテストって結構至難の業でexportsされてるメソッド経由でテストしてたり、テスト用に
var local ; exports.test = local = {}; local.privateMethodA = fucntion () {};
とかしてきってたんだけど、がんばればこういう規約的な回避方法以外にも道があるみたい。
Nodeにはvmモジュールがありますよね
このモジュールのAPI読んでくとcontextを自由に渡してコードを評価するやつがある。
vm.runInContext(code, context, [filename])#
vm.runInContext は code をコンパイルして、 context をコンテキストとして実行し、その結果を返します。 (V8 の) コンテキストは組み込みのオブジェクトと関数と共に、 グローバルオブジェクトを含みます。 実行されるコードはローカルスコープにアクセスせず、 context が code にとってのグローバルオブジェクトとして使われます。 filename はオプションで、スタックトレースでのみ使用されます。
つまりテスト対象のファイルのcodeをfsから抽出してvm.runInContextにセットしてcontextを適当につくってその参照を手元に残しながら第2引数に渡せば手元にのこったcontextの参照を使って局所変数テストできるんだぜって話です。
ここでいうcontextは変数オブジェクト(アクティベーションオブジェクト)だと思ってください。
そしてさっきのサイトにのってるその辺やってくれるコード
// module-loader.js var vm = require('vm'); var fs = require('fs'); var path = require('path'); /** * Helper for unit testing: * - load module with mocked dependencies * - allow accessing private state of the module * * @param {string} filePath Absolute path to module (file to load) * @param {Object=} mocks Hash of mocked dependencies */ exports.loadModule = function(filePath, mocks) { mocks = mocks || {}; // this is necessary to allow relative path modules within loaded file // i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some var resolveModule = function(module) { if (module.charAt(0) !== '.') return module; return path.resolve(path.dirname(filePath), module); }; var exports = {}; var context = { require: function(name) { return mocks[name] || require(resolveModule(name)); }, console: console, exports: exports, module: { exports: exports } }; vm.runInNewContext(fs.readFileSync(filePath), context); return context; };
を使えば最初あげたコードがこんな感じでテストできます(mocha使ったテスト)。
// test-app.js var assert = require('assert') , loadModule = require('./module-loader').loadModule ; describe('#untestableMethod', function () { var appContext = loadModule('./app.js') ; it('引数を足した結果を返すこと', function () { var actual = appContext.untestableMethod(1, 2) ; assert.equal(actual, 3); }); });
あとはテストするだけ
$ mocha test-app.js --reporter spec
#untestableMethod
✓ 引数を足した結果を返すこと1 test complete (2 ms)
これでがんがんexportsされてない関数テストできますね。
幸せ度高いのでvojtajina氏に感謝。
cssのcounter()って便利だよなーって話
TL見てて@watilde氏がこんなこといってるの見て
でもcounter()の存在知れてよかった。何か使い道ありそう。
— わっちさん (@watilde) 2013年3月16日
昔制作さんにもらったテンプレでcounter()使われてたときはjsで制御しなきゃいけないだろーなって思ってところばっさりいらなくなったのでかなり感動したなーって思い出してあれだったのでサンプルコード書いてみた。
サンプル(動きはResultを参照)
ぐぐったほうが正確な使いかたでるだろうけどcounter-incrementすればcssでカウンター機能が実現できるよってやつ
.item-first { border-top: 6px solid #069; counter-reset: item; } .item-raw { border-left: 6px solid #069; border-right: 6px solid #069; border-bottom: 6px solid #069; padding: 5px; height: 2em; line-height: 2em; } .item-input:before { counter-increment: item; content: counter(item) ") "; }
jsfiddleのサンプルみたらわかるけど要素なくなったり増えたりしたときに自動計算されるのでjs制御がごっそりなくせて幸せ度高い。
たとえばcss counter()使わなかった場合は
1)
2) <-こいつ消す
3)
ってしたときに
1)
3)
ってなって番号振り直す必要があるけどcounter()様はこの辺をよしなにやってくれる。
あ、ちなみに例のごとくie7はサポートしてません(^q^)
スマホサイトとかだともはや普通に使えるのでオヌヌメ
Node学園祭2012でおっぱいの話をしてきました。
11月下旬ごろ?にNode学園祭がありましたが、そこでLTしてきました。
前の記事でかいたNode Knock Outの話です。
NKO中にお世話になってた@mesoさんがよかったらLTしない?みたいなチャンスをくださったのでこれは是非といった感じで参加させていただきました。
資料
動画もとっていただいてたみたいです。
Video streaming by Ustream
http://www.ustream.tv/recorded/27109619/highlight/305836
間際でのエントリーということもあって大トリの発表になって緊張しちゃったけどやってよかったです。
あのあと色々と声をかけていただいて友達も増えました(切実)
すばらしい機会を与えたくださった@mesoさんやnode学園祭スタッフのみなさん、nko/学園祭のスポンサーのみなさん、本当にありがとうございました。
Node Knock Outに参加してきました。
※年末にかこうかこうと思ってかけてなかったやつを精算しようと必死になってかいてます。
時はさかのぼること11月の中頃にNode Knock OutというNodeのハッカソンがあったので参加してきました。 (http://nodeknockout.com/)
数年前からやってるやつで去年はnodeでオーケストラとかいうよくあるみんなで演奏して曲をつくろうぜ的なやつをやったのですが作品はできたもののdeployにはまってタイムアップするとかいう残念な結果だったので今回はそのリベンジもかねての参加でした。
で、今回は何を作ったかというと「おっぱい」を作ってきました。
作品名は「double mountain」です。
http://nodeknockout.com/teams/kusattamikan
残念ながらもうjitsuから提供していただいてた大会用のクラウドサーバーは落とされてるみたいですけど動画とかは残ってます。
4人チームでやってて
@nazomikan (フロントのおっぱい担当)
@to_muu_mas (触りまくったときのビーム担当)
@kuwabarahiroshi (他プレイヤーのカメラ位置表示担当)
@yokoyahhman (触ったときの音声担当)
でつくってました。
フロントの描画に関してはwebGLを使ってごりごりと。
やりはじめて数分で生でやってたら死ねると把握したのでthree.jsを使いながらやってました。
四角い面の集合をでポリゴンを生成するので四角形の頂点A-B-C-DをA-B-D-Cにして構成していくループなど色々と細かい工夫は必要ですけど概ね簡単に作ることができました。
ビームに関してはthree.jsが用意しているポリゴンのひな形のサイズなどを調整してアニメーション処理をかける感じで。
声の部分はopenjtalkで合成してaudio apiから再生したりなどして実現してます。
このへんで難しいのは衝突判定で、ブラウザからみてる限りとれるマウスの座標はx,yだけでzはとるのが非常に難しいんですね。
カメラの向きのベクトルから計算してz座標をエミュレートする感じのやりかたがthree.js側で用意されてたのでそれを使いました。
three.jsは神です。
カメラ座標の共有とかはwebsocketを使ってサーバサイドに現在のアングルを送ってそこからブロードキャストするようにして表示してます。
こうやってみるとNodeの成分がかなりうすいようにみえますけど、わりと内容も内容ということでみんなおもしろがって絡んでくれて非常にこっちもうれしかったです。
会場提供はドワンゴ様がしてくださっていたので非常に回線とかも含めてスムーズにことが運びました。
本当にドワンゴのみなさんありがとうございました。
まぁそんな感じで最終的な順位は上位にかすりませんでしたけど有意義な2日間でした!