超今さらExpress触ってみた - その2 Routerと実際のRequest Handlerを分けたい -

超今さらExpress触ってみた - その1 Expressって生々しすぎない? の続き。

今回は routing と実際の request を処理する function を分離します。

Request Handlerをroutingから独立させる

前回のコードの中のアプリの部分は

app.js

module.exports = (app) => {
  app.get('/', (req, res) => {
    res.send('Hello Express')
  })

  return app
}

このようによくある routing に closure をそのまま渡す形のまま終わっていますが、これを router.js, index.js に分けます。(なぜ handler.js じゃないかは次回明らかになります。)

app.js 改め router.js

const IndexHandler = require('./index')

module.exports = (app) => {
  app.get('/', IndexHandler)

  return app
}

request handler には function reference を与えておくと、引数は勝手にいい具合に渡ってきます。

index.js

module.exports = (req, res) => {
  res.send('Hello Express')
}

ちなみに server.js はこんな感じ。

const express = require('express')
const morgan  = require('morgan')

let app = express()
app.use(morgan('combined'))

app = require('./router')(app)

app.listen(3000, () => {
  console.log('Starting server localhost:3000 ...')
})

app.js じゃなくて router.js を require してます、ってだけ。

これをやって何が嬉しいのか

Google Cloud Functions の HTTP Function は以下のような形をしています。

exports.helloGET = (req, res) => {
  res.send('Hello World!');
};

そうです。

HTTP Tutorial  |  Cloud Functions Documentation  |  Google Cloud

上の Handler だけを取り出したうえで名前付き exports になった形なのです。

ということで、残りは

  • handler を名前付き exports にする
  • そのうえでテストコードを書く

とやれば少なくとも ExpressJS のテスト周りの知見を Function の開発に活かせる、とまぁこういう寸法です。

つづき

超今さらExpress触ってみた - その3 Cloud Functions Emulatorでも動くようにする - あーありがち(2018-09-12)

Yahoo! Pipes 始めました

Yapra Yapra 言ってたかと思えば今度は Yahoo! Pipes を動かし始めました。

Pipes: Rewire the web

Yahoo! Pipes のメリット

  • 作った Pipe もそれを利用したできた feed も Yahoo! がホスティングしてくれる

なんと言っても Pipes を利用する最大のメリットはコレ。Yahoo! だし、さすがにそうそう落ちないでしょ

Yahoo! Pipes のデメリット/苦手なこと

  • 編集しにくい

いきなり最大のウリの一つ、ビジュアルプログラミングを真っ向から否定してしまいますが^^;

Yahoo! Pipes は pipe の概念をビジュアルによく表現できていると思うけれど、pipe ってのは基本的に何段にも重なるもので、filter 一つ一つが全部ビジュアルになってしまうとどうしても編集に利用する画面にそれなりの大きさを要求してくるようになる。

簡単に言うと、やってる仕事はたいしたことないのにやたらでかい画面が必要になってしまう。

  • グローバル企業 Yahoo! 様とは思えない仕打ち

feed の charset が HTTP response header にない場合は化ける。まぁこれは分からんではない。日本の Web 屋的にはそんなもんある程度は許容しろよと思わなくもないが。そんなことより pubDate から timezone を捨てている!

あほか。

何が起きるかというと、feed を pipe で編集して吐き直すといきなり9時間ずれるのだ。どうするかっていうと地味に 9時間分引いてやるのが今のところの解法のようだ。

cf. 2008-04-18 - Never ending cycle

  • サーバもネットワークもクライアントも余裕がないといけない

やっぱちょっと厳しいですな、これ。基本的に JavaScript で画面いっぱいにいろんなオブジェクトを広げてるわ、その指示に基づいてサーバは始終あちこちのサイトにアクセスして feed を取得、各種フィルタを適用してあれこれ値を返してきまくってくる。どこに対しても優しさがない。

まとめ

ビジュアルプログラミングってのはあんまり縁がないんだけど、やっぱ苦手意識は消えない感じ。基本的にはエディタと CLI が最強だと思ってる人間なもんで。1でもその場でできた feed のホスティングまでできてしまうところがやはり嬉しい。

しかし、文字化けの問題は厳しい。検索エンジンを自分でこさえている会社とは思えない放置ぶり。なんとかしてください! やってみると分かるけど、案外扱えない feed がたくさんあるよ!

また、地味なところでは twitter の feed を取得することがほとんどできない。これは twitter の API 制限に引っかかってるってことなんだろうけど、この問題は認識してるけど1ヶ月以上経った今も解決してる気配はない。

cf. Pipes Blog » Blog Archive » Twitter and Pipes

※ これは推奨しない方がいいのかもしれない(たぶん重たい)けど、実は search.twitter.com からならほぼ問題なく取得できる。

微妙な点の方を多く書いちゃったけど、文字化けが起きなくて単純な処理だったら Pipes はとても楽しいし便利。もちろん単純じゃない処理だってある程度辛抱強ければ可能。ちなみにこの前、CNET Networks の吐いてる feed をひとまとめにして uniq 掛けるものを作ってみました。便利便利。

Pipes: Combined CNET Networks(Japan) Feed

  1. Squeak が気になりながらどうしても手が出ない、というか手を出しても自分がフリーズしてしまうのもその辺が理由なんだなぁ。 

svndumpfilter は意外と使えない

というのも、svn copy を利用してあちこちの branch で作業したファイルはその branch も include しておかないと途中で svndumpfilter が不正なパスとか文句言って止まっちゃう。こういうファイルが大量にあると include の引数がとんでもないことになってしまう。

結果、構成によるんだろうけど、手元のものは filter 掛ける前とほとんど変わらない状態にしかならなかった。容量で言うと1割ちょいしか減らない。欲しいのはもっとずっと一部なんだけど。うーん。リポジトリの分割って難しいな。svndumpfilter に force オプションとかあればいいのに。それか手作業? それとも revision を細かく指定しながら incremental に dump して cat?

うーん。

試しに dump ファイルを自前でパースして必要な Node-path の含まれる Revision-number だけ吐き出すスクリプトを書いてみた。この結果出力された revision だけを次々 dump していって、新しいリポジトリに load したら目的のものができるだろうか?

まだ実験は続く。

#! /usr/bin/env ruby

rev = 0

while ( line = gets )
  line.chomp!
  if ( line =~ /\ARevision-number: ([0-9]+)\z/ )
    rev = $1
  end

  if ( line =~ /\ANode-path: (.*)\z/ )
    if ( $1 =~ RE )
      puts rev
    end
  end
end

実際に使ったものとちょっと違うので試してないけど、必要なところを直せばたぶん動きます。あれこれめっちゃ決め打ちです。出て来た数字の羅列を uniq してください。たぶんこんな感じ。

ruby SCRIPT dump-file | uniq > DEST

uniq 持ってない人は while の中で rev を配列にツッコんで最後に

puts array.uniq.join( "\n" )

してください。(最初そうやろうとしたけど、瞬時に動作の様子が見れなくてむかついたのでやめたのでした。)

[追記] 厳しい。

必要な revision だけを dump しても結局 revision の完全な状態を再現可能な dump を作成するので意味がない。–incremental を付ければその前の revision からの差分で dump してくれるが、revision 減らそうって言ってるんだからこいつらを load しまくっても正しくリポジトリを復元できない。

可能な対応は、フル dump に対して、関係する path が含まれていない revision あるいは node を削除していく、というスクリプトを作ることか? でもそうすると dump ファイルを自前でちゃんとパースできないといかんな。(上に挙げたものはかなり適当。)それとも完全自動化は諦めるか? うーん、それもつらい。できなくはないと思うけど。基本的には

Revision-number:
Node-path:
Node-path:
..
Revision-number:
..

こういう構成なので、除外したい Node-path や Revision-number を切っていくのは順番になめていくだけで可能。

つーところまで分かったところで、他にやることがあるのでこれは後回し。誰か作ってくれないかしら。

でもなんか新しいリポジトリでは昔の歴史は思い切って捨てるという判断がいちばん正しいような気がしてきた。負けですか?

※ 最終的には手作業での dump ファイル修正を含めて目的の形にリポジトリを分割することができました。

cf.

あ。PukiWiki 1.4.4 が出てる。

1週間前に。

UPDATING からコピペ

4. 初期化処理(init.php)が大幅に見直され、PukiWikiにとって不要なグローバル 変数(特に、危険なデータを含んでいるもの)が積極的に削除(unset)される様に なりました。具体的には $_REQUEST, $HTTP_GET_VARS, $HTTP_POST_VARS, HTTP_USER_AGENT 関係, REQUEST_URI 関係, QUERY_STRING 関係のデータにアク セスしていたサードパーティ製プラグインやカスタマイズ部分は、適切に動作 しなくなるでしょう

本体添付のものは ok ってことか? あとは

  • 初期設定がいくつか変わっている
  • 複数の Wiki を立てやすいように構成が見直され、変数が追加されている
  • 様々な UA に対応する設定が含まれている

くらいかなぁ。細かいバグ取りはどーもお疲れさまってことで。

About

例によって個人のなんちゃらです