Content-Encoding: deflateなHTTPレスポンスを作る

投稿者 akira 2010-03-11 07:26:00 GMT

Content-Encoding: deflateなHTTPレスポンスを返させる簡単な方法はないかなと探してみたらRackがサポートしていた。どうやるかというと:

use Rack::Deflater

これだけ。ruファイルに書いておけばよい。発端がちょっとしたテストのためだったので、内容はなんでもよく、とにかくdeflateで返してくれれば十分というわけで、こんなのを書いて目的を達成できた:

module Rack
  class Foo
    def call(env)
      r = Response.new
      r.write "abc123"*100
      r.finish
    end
  end
end
use Rack::Deflater
run Rack::Foo.new

実際にアクセスしてみるとこうなる:

$ ruby -r open-uri -e 'open("http://localhost:9292/"){|h| p h.read}'
"abc123abc123 ...(略)..."
$ ruby -r open-uri -e 'open("http://localhost:9292/", "Accept-Encoding"=>"deflate"){|h| p h.read}'
"\355\3011\001\000 ...(略)..."

Termtterでハッシュタグを追跡する

投稿者 akira 2009-10-29 02:04:00 GMT

Termtterのタイムライン表示でハッシュタグをいっしょに表示できるといいかもと思い、ちょっとやってみた。auto_search.rbと名付けたプラグイン。

タイムラインが更新される前後のフックを使って、あらかじめ指定しておいたキーワードで検索を行う。指定方法はコマンドライン(?)から以下のようにする。

auto_search #termtter #ruby

この例では二つのハッシュタグを検索対象としている。三つでも四つでも、たぶんハッシュタグではないキーワードでもいけると思う。ただ、いろんな検索パターンをテストしたわけではない。

検索対象から外したくなったら以下のようにする。

remove_auto_search #ruby

特に指定しなければタイムラインの更新間隔の3倍の時間ごとに検索を行うようにした。間隔を指定したければ検索キーワードの後に「/n」で何倍にするかを指定する。「#termtter/1」ならタイムラインの更新があるごとに検索を行う。

「/」を含んだり空白を含んだりするキーワードを指定するには「'」か「"」でくくる。ただし、キーワード自体は単に検索APIに投げているだけなので、単語以外の指定にはもしかしたら何か注意が必要かもしれない。

~/.termtter/configでの指定は以下のようにする。

Termtter::Client.plug 'auto_search'
config.plugins.auto_search.keywords << '#termtter/2'
config.plugins.auto_search.keywords << '#rubykaigi'
config.plugins.auto_search.keywords << '#tork02/2' # とちぎRuby会議02
config.plugins.auto_search.keywords << '#RHCBK/4' # RubyによるMac OS Xデスクトップアプリケーション開発入門

config.plugins.auto_search.keywordsが検索キーワードを設定するための配列になっている。キワードの書き方はコマンドラインでの書き方と同じ。この例では一語ずつ追加しているが「config....keywords = '#termtter/2 #rubykaigi ...'」のように指定しても構わない。

ある程度はテストをしてきているが、なんとなく動いたっぽいというところでしか見ていない。取りこぼしや検索しすぎなどあるかもしれないので注意して。

Capistranoで上位タスクと同じホストを強引に処理対象とする

投稿者 akira 2009-10-03 00:41:00 GMT

Capistranoのタスクは実行対象ホストのリストをホスト名やロール名で指定できる。この指定は静的なものなので、あるタスクから別のタスクを呼び出したとしても、それらの指定は引き継がれない。

以下のレシピでタスクbarには:hostsオプションがあり、これに従って同タスクはhost3とhost4に対して実行される。barから呼び出されるタスクbazにはこのような指定がないため、barでの指定によらずロールに登録されている全ホスト(host1とhost2)に対して実行される。

role :foo, 'host1', 'host2'
task :bar, :hosts => %(host3 host4) do
  run "..." # host3とhost4でコマンド実行
  baz
end
task :baz do
  run "..." # 全ロール(host1とhost2)でコマンド実行
end

このような動作をするため、タスクを部品化して再利用しようとすると、ある程度のところからはメソッド定義をしていくことになる。

ここでふと、いいかげんなオブジェクトを渡せばそのあたりの動作をコントロールできかなと考え、その思い付きのまま試みにコードを書いてみた(gist)。テストは一部だけ(しか書いていない)。

uh, ul = UpstreamSupport.create(self)

role :foo, 'host1', 'host2'
task :bar, :hosts => %(host3 host4) do
  run "..." # host3とhost4でコマンド実行
  baz
end
task :baz, :hosts => uh do
  run "..." # 呼び出し元と同じホスト群でコマンド実行
end

このレシピのタスクbarを実行するとhost3とhost4でコマンド実行される。そして、そこから呼びされたタスクbazでも同様にhost3とhost4でコマンド実行される。しかし、タスクbazを直接実行すると、全ロールのホスト群、つまりhost1とhost2でコマンド実行される。さて、うまく動くかな?

ただ、あんまりふみこみすぎてもなってところでもある。

Ruby 1.8.7-pXX v.s. Capistrano 2.5.x

投稿者 akira 2009-07-31 11:41:00 GMT

最近のRubyでCapistranoを実行しようとすると、対象ホストが二つ以上のときにかなりの確率でハングアップしてしまうことに気付いた。しばらくは見て見ぬふりをしていたのだが、仕事に少し関係しそうな気配もあって、調べてみることにした。

1.8.7-p72では問題なかった記憶があり、1.8.7-p174で現象が出ることは確認済み。ということでtagのある1.8.7-p72、1.8.7-p160をかわきりに、ruby_1_8_7におけるversion.hのcommit logを手掛かりに二分探索の雰囲気を出しつつ絞り込みをかけていったところ1.8.7-p135で現象が現れることがわかった。

このパッチレベルでの修正内容はruby-core:20446である。が、これを見ても具体的にどういう影響が出ているのかはわからない。修正内容からするとむしろ状況がよくなってくれそうなものだが…… などと思いつつ、試行錯誤を繰り返した。

まず、Capistranoでの問題はNet::SSHで起こっていることがわかった。Net::SSHではIO.selectを使っいながらソケットから少しずつ読み出すということをしている。これにThreadを組み合わせると現象を起こせる。たとえばこんな感じ:

require "net/ssh"
["localhost","localhost"].map {|h|
  Thread.new{ Net::SSH.start(h, "foo") }
}.each {|t| t.join }

次に、修正内容と見比べつつさらに試行錯誤し、結局はdebug printをいれてスレッドの動きを追いかけた。かなりおおざっぱな読み方しかしていないので間違っているかもしれないが、なんとなくこんな感じの動きのようだった:

  • 読み出し可能になるのを待っているスレッドがある
  • そのスレッドで読み出し可能になる→th_foundに値が入る
  • 次にスケジューリングのためスレッドを順番に見ていくが
  • 運悪く、th_foundなスレッドに到達する前に「次」に実行可能なスレッドが見付かってしまう

現象からいうと運悪くというよりは運良く処理が進むことがあるといったところで、ほとんどの場合、上の再現例の二つのスレッドがゆずり合うような形になっている。

そこで、試みにth_foundしたスレッドにできるだけ処理がまわるよう、スレッドのプライオリティが同じときにも「次」候補のチェックをするように以下のような変更を加えてみた。

--- eval.c	(revision 24335)
+++ eval.c	(working copy)
@@ -11228,7 +11228,7 @@
 	    break;
 	}
 	if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
-	    if (!next || next->priority < th->priority) {
+	    if (!next || next->priority <= th->priority) {
                 if (th == th_found) {
                     th_found->status = THREAD_RUNNABLE;
                     th_found->wait_for = 0;

Capistranoでの動きをざっとみたところではこの変更で止まらずに動くようになった。Rubyのテスト(threadのみ)をまわしてみた限りでは影響はなさそう。はてさて。

……という話をIRCでしてみたところmputさんがredmineに登録してくれた(Bug#1848ruby-dev:38971)。あと多分、これは同じ話だと思う。

追記(2009-08-07)

少なくとも上の変更ではまずいと思えるので変更を出しなおしたのがruby-dev:39003。ただ、それでもまずい感じはするよねと思っていたところ、やはり好しくないらしい。

それではということで再現コードを小さくして、debug printで動きを追いかけてみたのがruby-dev:39037になる。th_foundとはちょうどあべこべにスレッドが選択されている…… ような気がしている。

追記(2009-08-10)

ruby-dev:39042にある通りr24442で修正された。

Ruby会議2009三日目

投稿者 akira 2009-07-19 10:00:00 GMT

三日目、最終日のざっくりメモ。

  1. ソケットライブラリの改善
    • 起きてustreamつけたら始まっていた
    • ちょっとだけ聞きながら出掛ける準備
    • で、移動開始
  2. コーヒータイム
    • 休日の神保町はすいてていいなあ
    • +自転車な生活にあこがれる(まあ世の中は休日だけじゃないんだけど)
    • なごりおしみつつ移動
  3. スポンサーブース
    • 午後のセッションが始まるまでにまだ少しあったのでスポンサーブースをふらふらする
    • 実は、今日、このときまでスポンサーブースが中会議場にあることを知らなかった
    • RICOHさんのブースにて
      • RubyとかRailsとかで始めるのって社内的にどうでしたか? とか
      • クライアントの種類を増やすとかAPIとかって考えてますか? とか
      • 予定通りにユーザの増えてる感じです、とか
      • いろいろ質問(あとでquanp使ってみよう)
      • 開発者の福田さんがいらしてまたいろいろ質問
      • 鳥取開発センターなだって! とか、ボスが米子工専なんだって! とかいろいろおどろく
      • 始めた経緯も興味深かった(昨年か一昨年のRuby会議で発表されたそうだが、参加してなくて追ってなかったので知らなかった)
      • 鳥取でも何かできそうですよね、なんて話もしたり(勉強会とかあったら行っちゃおうかな)
    • クリアコードさんのブースにて
      • ていうか須藤さんとおしゃべり
      • ActiveLdapってすでにdebがあるんですよ→おお最新になってる→この人にrabbitふっちゃうとか→実はAr-さんに話をしてみたんですよ→おー、それはいいですね、などなど
      • あと、仕事の具合いはどうですかーとか、学校環境で求められるdistroの特徴はーとか
    • SKIPさんのブースにて
      • 某所でSKIP動かしてらもらってみたりしたんですよ(これ、ふり返ってみると意味わかんないこと言ってしまっているなあ……)、一人SKIPはさすがにせつないですよね
      • まだ今みたいにRubyとかRailsとか話題になる前ですよね、始めるの大変じゃなかったですか? とかRICOHさんでも聞いたこと
      • いろいろな事情があって始まったというようなところがあったんだけど、その事情のおかげ(?)でわりあいすんなり、というような話
    • で、ゆっくりしていたら原さんのセッションをのがしてしまった
  4. RubyCocoa/HotCocoa(RHC) ~RubyではじめるMac OS Xデスクトップアプリケーション開発~
    • タイトルが変わったんだけど、なんだったかな
    • なんていうか、今手元にMacがないのでなんでなんだ? と自問する時間だった
    • なんとなく軽快な印象を持ったせいか、Airでどこでもハックだよね、とかかなり軽いことを考えてしまった
    • でも持ち運べるMacはやっぱり欲しいな(最近、仕事で出ることが増えたというのもある)
    • RubyCocoa本が待ちどおしい
  5. RubyをつかったiPhoneアプリケーション開発
    • iPhoneでRubyが動いたとかってニュースが流れたのは知っていたのだけど、動いているところ(プレゼンの関係上エミュレータだったけど)を見ると動かしてみたくなる
    • iPhone上で動いているirbに外部からtelnetで接続して操作するというデモ
    • Objective-Cで作られたiRubyKaigi2009にirbを組み込んで、動的にいじっちゃうデモ
    • アプリケーションとリリースするのはいろいろグレーな感じもあるのだけど、RubyCocoa 0.5ではARMバイトコードをはけるはずなのでそれでiPhone開発とかできるようになりそう(とかって話だったかな? ちょっとあやしい)
    • 何から始めればいいんだっけ? というところからだけど、これ、動かしてみよう
  6. Erubis徹底解説
    • 速いeRubyの実装という認識だったのだけど、そうではない部分でかなり興味深いErubisの話
    • テンプレートにBindingではなくてHashやObjectを渡せるようにしてある
    • メソッドが細く分かれているので拡張がやりやすい
    • eRubyからCとかPHPとかいろんな言語のコードを出力できる
    • eRuby→Rubyの変換結果をキャッシュしちゃう
    • erubis -XでeRubyに埋め込まれたコードの部分だけを変換して出力することができ、デバッグ時に便利
    • 埋め込みコードが文か式かによって前後の空白文字を制御することで、余分な空白問題をシンプルに解決(<%か<%=かっていう話だったのかな)
    • form_forの実装はなかなか気持ち悪いのだけど、eRuby的には限界というか未定義な感じ
    • eRubyはテキスト処理系であってテンプレートではない→これからはTenjin
    • 裏番組が強力すぎたのがもったいない、地味に富む面白いセッションだった

というところで、ちょっと早いけど帰ってきた。

Poken的成果は7人。これが初めてのハイフォー体験となった。ふと思ったのだけど、たとえばRubyKaigiというPokenを作っておいて、来た人は勝手にハイフォーしてねとかはPoken的にどうなんだろうか。(どうもこうもないかも。)

この手のイベントに出るのは久しぶり…… ではなくて、とちぎRuby会議に行ったんだった。ただ、こういう人数の中に入るのは久しぶりだったので、ずいぶん疲れたけども楽しかった。人々と会えるのはなんだかんだいいつつも、何かしら動く部分があるのがよいのかな。

もう少し何か貢献できることがあればなあ、なんて思う。まずはDebianやVineでの活動レベルをキープしていくことからだろう。何はともあれruby1.9をsidに。あー、1.9.1をsidに、1.9.2preをexperimentalに、とかやりたいな。早く調整をしてやっつけよう。

Ruby会議2009二日目 1

投稿者 akira 2009-07-18 12:47:00 GMT

本日のざっくりしたメモ。

  1. コミュニティアピール
    • この途中あたりで会場に入った
  2. 基調講演
  3. Lightning Talks
    • Decimal - BigNumを使ったBigDecimalの小さくて速い再発明で、かつ、好ましい再発明の事例
    • morumotto.com - One-Time Passwords for OpenIDというのがそもそも興味深いが、その上日本の携帯電話への対応も行われているとか
    • rubyrep - 非同期・マスタ-マスタのRDBレプリケーション(そのうち動かしてみたい)
    • ギャルゲーはやらないのでわからないけど、趣味.rbはちょっとおもしろそう。
    • Rubyでの(力技)でのネットワーク運用 - 実際のコードや開発の様子をもう少し聞いてみたかった
    • cdn.debian.net - 広く使われているRubyコードとしてはなかなかの実績・事例だと思う
    • ActiveLdap - LDAPってちょっと使うにはめんどうなんだよね…… ということで自分ではあまり使わないのだけど、これならちょっとコード書けばって気になる(debもある)
  4. 分散並列処理フレームワークfairyと分散オブジェクトシステムDeepConnect
    • map reduceの考え方をベースにした大量データ処理のフレームワーク
    • 分散ファイルシステムのほうにも興味があったり
    • 領域的にはdRubyと重なるところも多そうなDeepConnectの位置付けや今後の動向が気になる
    • 早くコードが出てこないかなあ
  5. 偉大なBigTableとぼくのおもちゃ
    • map reduceが続く
    • 世界をコントロールブレイク
    • 咳さんの話はおもしろいなあ
    • dRuby本とdrb/*.rbを読み返してみたくなった(時間をとっていずれ)
  6. Regional RubyKaigi会議
    • RubyKaigiを開くというようなつもりは少なくとも今はないのだけど、都内以外での勉強会開催という点でヒントが得られないかなと思って参加
    • BoFのような感じ
    • 「RubyKaigi」という名前には運用ポリシーのようなものがあったということを知った
    • とはいえ強いルールではなくて、こういうイメージというようなもののようだ
    • だが、それがどんなものかっていうのは正直わからなかった――開催者間ではある程度の共通認識があるようだ
    • この間のDebian Ruby1.9 Kaigi(Debian Ruby 1.9会議)は抵触していないとされていたようだが、CAのきわきわだった(○○Ruby○○Kaigiのような字面には要注意)

Reginal RubyKaigiはまだ二回目をやった地域が出てきていない。その点に関連して、前回の○○RubyKaigiのスタイルが重しになってしまって二回目、三回目が(気持ちの上で)開きにくくなるようだとよろしくないという発想があるようだ。では、というので、内容的にゆるくくだけたRubyKaigiをどこかやってくれればその後から楽になるのではないかとか、地名ごとに回数をカウントするのではなく全体で通し番号にすればいいのではないか、などの案が出ていた。反対に、東京のようにいろいろな集まりがあるところは別とすると、むしろ「前回」を続けることである種の場を作りたいという意見もあった。

個人的には地域Ruby会議というくくりのなかでは名前、特に地名が入るというのは重要であると思う。ダブルネームでという声も出ていたが、参加する人がどう呼ぶか、どのような認識で参加するかがポイントだから、なんとなくズレた話のように思えてしまった。とはいうものの「RubyKaigi」の背景にある何かというのがどうにもわからないのでそこのところはなんとも。通し番号にするくらいなら名前はなんでもありにして「後援 日本Rubyの会」でいいんじゃないの? とか思ったんだが…… そういう話でもないのかも。

ふりかえって横浜。横浜Ruby会議というのはあってもいいんじゃないかという意見は出たが、私としては東京に近すぎるのでいまいちかなとも思っている。もちろんやろうって人がいたらお手伝いくらいはできるかしらと考えてみるが、やっぱり自分ではやらないだろうなと思った。横浜Rubyistってあんまりピンとこない――のは私が知らないだけかもしれないけれど、何か色が出せるのかというとこれまたピンとこないから。

だからこそまずは「集まってみない?」というのがあるわけで、そのとっかかりとしても勉強会はやってみようという気になっている。意外とDebianネタにも引き合いがあるようなので、難しくないDebian系の勉強会(難しいのはDebian JPでやってるし)とともにRubyネタも何か考えよう。とりあえずCapistrano、だが、それ以外にあまり手持ちのネタってないのだよなあ。話を聞いてみたい人を挙げてもらって、その人に来てもらって、質問しまくるなんてのは面白いかも。

ま、そんなこんなで、「Ruby,Railsによる「ケータイ」ポータルの作り方!」や「CとRubyとその間」なんかも気になったけど行けなかった。後で映像を見られるようになるのかな?

Ruby会議2009一日目

投稿者 akira 2009-07-17 14:16:00 GMT

本日のざっくりしたメモ。

  1. 出張版toRuby
    • dRubyでP2Pぎみに相互接続する演習など
    • 思ったようなやり取りができなかったり
    • ネットワーク接続がうまくいかなかったり
    • 解決していきつつ理解が進んでいたようだ
    • マシンを持っていかなかったのでネットワークへの参加はしなかったが楽しかった
  2. 現場で役立つRuby on Railsパターン
    • 実際に書いている人の生っぽい話
    • 10人以上で数か月かけて開発し二年くらいはメンテナンスする、という想定
    • こうするとコード運用がうまくいくというノウハウ
    • Railsフレームワーク上に用意された「コードを書ける機会」がこれこれとあって、そのうちのどこにどんなコードを配置するのかをよく考える――というのはなるほどと思った
  3. 『エンタープライズRails』に学ぶ企業ユーザのためのRails活用の極意
    • エンタープライズという視点ではRDBMSの機能を積極的に使う必要がある
    • その事例を「エンタープライズRails」からいくつか引用して説明
    • Railsの進化とは異った系統での知見に触れられる「素晴らしい本」なので買おう、と思った
  4. toRuby会議(?) - ソファで
    • 咳さん、中内さん、YuzoさんとtoRubyの話題
    • 今後のtoRubyを〜とか、勉強会は〜とか
    • 教える・教わる、みんなでやってみよう、質問を作ってこよう、しゃべりたい人がしゃべる、など、各種の形態を考えてみては準備とか進め方とか雰囲気がどうなるか、なんてことなまったりと
    • 関西のRuby勉強会って若い人が多いのかな?
  5. Lightning Talks
    • いくつか興味を持った
    • peeled unshiu - とりあえずさわってみたい
    • Arabesque, a brand new Ruby queue - BDBを使ったqueue? 見てみたいと思ったんだっけど、どこかに出てるんだっけ?
    • lang-8 - SNS自体はRailsなのかな?
  6. 懇親会
    • 色紙とペンが配られる
    • 互いにサインをもらっちゃいましょう、というのはあれだけ人が多いとなかなか面白いと思った(けっこうもらえた)
    • いろんな人といろんな話; がんばって思い出してみる……
    • 先日書いた勉強会ネタに興味アリという声をもらえた(ちょっとほっとした)
    • ふつパイラ、RubyCocoa本の話など
    • 末永さん、須藤さんとごあいさつ: rabbit.debどうしましょ→スポンサー探しましょ→groonga.debもいっしょにつっこみたい、とか
    • 大場さんとごあいさつ: 小槌の話とか(あ、BookScopeも気になってたんだった…… 話を聞かせてもらえばよかった)
    • kdmsnrさん、yharaさんとごあいさつ: blogとかいろいろいつも読んでます、みたいな
    • 食べ物がたくさんあった(ただ甘い物はなかった)

あちことでコミッタをつかまえてはfingerprintを確認してもらった。みなさんありがとうございます。

Ruby会議2009のセッションのおすすめ情報

投稿者 akira 2009-07-16 11:47:00 GMT

 Ruby会議2009のセッションのおすすめ情報が出ているのは……

パッとわかったのはこんなところかな。○○だから来い、とか、目玉は○○とか、そういうのがあると助かる。

ところで英語のセッションには日本語サポートあるのかな?

Capistranoと仮想端末と標準入出力の関係

投稿者 akira 2009-06-10 00:02:00 GMT

次の二つのレシピの違いを考えてみる。

# (A)
task :foo do
  run "echo hello, world | dd bs=1 count=5 skip=5"
end
# (B)
set :default_run_options, :pty => true
task :foo do
  run "echo hello, world | dd bs=1 count=5 skip=5"
end

字面の上での違いは(B)の一行目、setで始まる行が(A)にはない点である。送信されるコマンドラインは同じであるから動作は同じかというと、そうでもない。これは実行してみるとわかる。だが、その前にrunで実行しているコマンドddの動きについて確認しておこう。ddはif=やof=で入力元・出力先を指定しなければ標準入力・標準出力に対して読み書きを行う。そして、読み書きを行った状況を標準エラー出力に書き出す。

上の(A)および(B)においては、echoにより標準入力に流し込まれた文字列を読み取り、オプションで指定された部分(6バイト目からの5バイト)を標準出力に書き出す。それでは実行結果を見てみよう(ある実行例からの抜粋)。

# (A)
  * executing "echo hello, world | dd bs=1 count=5 skip=5"
    servers: ["localhost"]
    [localhost] executing command
 ** [out :: localhost] , wor
*** [err :: localhost] 5+0 records in
*** [err :: localhost] 5+0 records out
*** [err :: localhost] 5 bytes (5 B) copied, 2.9705e-05 s, 168 kB/s
    command finished
# (b)
  * executing "echo hello, world | dd bs=1 count=5 skip=5"
    servers: ["localhost"]
    [localhost] executing command
 ** [out :: localhost] , wor5+0 records in
 ** [out :: localhost] 5+0 records out
 ** [out :: localhost] 5 bytes (5 B) copied, 3.03e-05 s, 165 kB/s
    command finished

似たような出力になっているが、よく見ると(A)には「out」と「err」があり、(B)には「out」しかない(一行少ないというのもあるが、それはまた別の話)。この違いはコマンド実行の際に仮想端末を要求したかどうかによる。(B)は仮想端末を要求していて、そのため、ddが標準出力に書き出した内容と標準エラー出力に書き出した内容の両方が、Capistranoには標準出力に書き出されたものに見えている。

とはいえ、これはCapistranoに限った話ではない。たとえば以下のコマンド実行例でも同じ状況を見てとることができる。

$ ssh -q    localhost "echo hello, world | dd bs=1 count=5 skip=5" >/dev/null
5+0 records in
5+0 records out
5 bytes (5 B) copied, 3.4422e-05 s, 145 kB/s
$ ssh -q -t localhost "echo hello, world | dd bs=1 count=5 skip=5" >/dev/null
(何も表示されない)

話を戻すと、こうした動作の違いは以下のときに問題になる可能性がある。

  • runやsudoにブロックを与えてコマンドの出力(特に標準出力)を取り込もうとしている
  • エラーが発生した(標準出力に何か書き出される)

どんなときにでも使える回避策というのはなさそうに思える。強いていえば次のどれか、またはすべてに気を付ける。

  • 標準エラー出力が不要であればコマンドライン上でリダイレクトして捨てておく
  • 受け取ったデータのうち必要と思われる部分だけをうまく抜き出す
  • 本当に必要なときにだけ:pty => trueを指定する

最後の点については、要するに:default_run_optionsに:pty => trueを入れるのは要注意だということになる。実際には、あらかじめ用意されたレシピを使うためなど、どうしようもないこともあるのだが、コントロールできるなら個々のrunやsudoにおいて:pty => trueを指定するといくらかマシになる。

Flickr APIの変化とTypo 5.3のflickr.rb

投稿者 akira 2009-05-30 13:17:00 GMT

Typo 5.3で使っている自作のFlickrプラグインで写真を引っぱれなくなった。「Flie does not exist」という例外が起きている。ファイル?

追ってみたところ、vendor/flickr/flickr.rbで使っているXmlSimple.xml_inの中での起きている例外だった。xml_inは与えられた文字列がXMLっぽかったらXMLとして、そうでなければファイル名として処理しようとする。えぇー、と思ったが、まあそれはおいていおく。

実際にアクセスしているURLを取り出してwgetしてみたところ、きちんとレスポンスが得られる。けれどもxml_inには空文字列が渡っている。おかしいなと思い、flickr.rbではどのようにアクセスしているか見てみるとNet::HTTP.get_responseを使っていた。それではと同メソッドでアクセスしてみると302が返ってきていることがわかった。なるほど。

では302が返ってきたらそれを追いかけるように書き換えて、などとしかけたのだが、open-uriでよいではないかと思いとどまった。こんな感じ。

def http_get(url)
#  Net::HTTP.get_response(URI.parse(url)).body.to_s # 元のコード
  open(URI.parse(url)) {|i| i.read}
end