preload
2月 27

Amazon Web Service の Simple DB を試してみたけど、なかなかリクエストの作成がうまくいかなくて、一回リクエストに成功したところで、明日も早いしもう寝るか、というポスト。へにょいリクエスト作成用の Ruby クラス付き。


Amazon Simple DB (以下、ASDB)
は Web ベースで利用できるデータベースサービス。REST やら SOAP やらでアクセスできる。利用には Amazon Web Service (以下、AWS) のアカウントと Simple DB サービスへのサインアップが必要。2007 年末くらいから公開されていたのだが、サインアップが遅れた (Limited Beta の) ため、順番待ちに入っていた。で、1 月末にようやく使えるようになった。
ちなみに、S3 やら EC2 と同じく従量課金。手軽にスケールアウトできそうな反面、規模によっちゃ実はそんなに安くないんじゃないの?とハマりそうではある。(EC2 立ち上げっぱなしで放置してたら $70/月 くらいかかった。)

ASDB では、Domain というデータセットのハコに Item という単位でレコードを追加していく。Item には Attribute という名前で属性を付加する事ができ、記録されているレコードには Query によりアクセスする事ができる。ちょっと強引に RDB のように解釈するなら、Domain がテーブル、Item がレコード、Attribute はカラムみたいなものだとおもう。

まず、REST の API を使って、上記でいう Domain を定義する CreateDomain アクションを試してみる。実際の利用には、AWS にサインアップして得られる AWS Access Key ID と AWS Secret Access Key が必要。

ASDB へのリクエストの構成要素は大まかに以下のような感じ。これを GET のパラメタに含める。

  • AWS Access Key ID
  • アクション
  • アクション毎に指定するオプションパラメタ
  • タイムスタンプ
  • APIバージョン
  • シグネチャバージョン
  • シグネチャ

ここで、最後のシグネチャは、以下のようにして作る。

  1. シグネチャ以外の構成要素 (AWS Access Key ID 〜 API バージョン) をキー名で昇順ソートする
  2. ソートしたペアのキーと値をセパレータとか付けずに単純に並べる
  3. 並べたパラメタを HMAC-SHA-1 にかけてメッセージダイジェストを得る。この時の秘密鍵に AWS Secret Access Key を指定する
  4. 得られたダイジェストを Base64 エンコードする
  5. 得られたエンコード文字列を更に URL エンコードする

このようにして得られたシグネチャを Signature 値としてリクエストに含める事で、ASDB がメッセージの正当性を確認してくれるというしくみ。

で、このリクエストを作成するクラスが以下のもの (AWSACCESSKEY やら AWSSECRETKEY はサインアップして得られるものを使う):

require 'openssl'
require 'base64'
require 'cgi'
class AmazonSimpleDb
BASEURI = 'https://sdb.amazonaws.com/?'
AWSACCESSKEY = 'Your AWS Access Key'
AWSSECRETKEY = 'Your AWS Secret Key'
def initialize
@params = Hash.new
@params.store('AWSAccessKeyId', AWSACCESSKEY)
@params.store('SignatureVersion', '1')
@params.store('Version', '2007-11-07')
end
def add_param(key, value)
@params.store(key, value)
end
def request_uri
uri = BASEURI
message = ''
(@params.sort_by { |x| x[0].downcase }).each do |e|
uri << "#{CGI.escape(e[0])}=#{CGI.escape(e[1])}&"
message << "#{e[0]}#{e[1]}"
end
hmac = OpenSSL::HMAC.new(AWSSECRETKEY, OpenSSL::Digest::SHA1.new)
hmac.update(message)
signature = CGI.escape(Base64.encode64(hmac.digest).chop)
uri << "Signature=#{signature}"
end
end

sort_by してるんで、Ruby は 1.8 以上で。パラメタは case-sensitive なのに、ソート時は case-insensitive だったり、生メッセージは URL エンコード不要だったり(そりゃそうか)、Base64 したら最後に改行文字が入ってたりにハマった。

これを AmazonSimpleDb.rb とかで保存して、以下のような感じで使う。タイムスタンプで指定してる日付は適当。DomainName に DoCoMo とか指定してるのは、機種情報 DB を作ってみようとしただけで、深い意味は無し。XXX やら YYY はダミーです。

$ irb -r 'AmazonSimpleDb'
irb(main):001:0> asdb = AmazonSimpleDb.new
=> #"2007-11-07", "AWSAccessKeyId"=>"XXXXXXXXXXXXXXXX", "SignatureVersion"=>"1"}>
irb(main):002:0> asdb.add_param('Action', 'CreateDomain')
=> "CreateDomain"
irb(main):003:0> asdb.add_param('DomainName', 'DoCoMo')
=> "DoCoMo"
irb(main):004:0> asdb.add_param('Timestamp', '2008-02-26T23:27:00-09:00')
=> "2008-02-26T23:27:00-09:00"
irb(main):005:0> asdb.request_uri
=> "https://sdb.amazonaws.com/?Action=CreateDomain&
AWSAccessKeyId=XXXXXXXXXXXXXXXX&
DomainName=DoCoMo&
SignatureVersion=1&
Timestamp=2008-02-26T23%3A27%3A00-09%3A00&
Version=2007-11-07&
Signature=YYYYYYYYYYYY" (実際は一行)

得られた request_uri にブラウザとか適当な https が行けるクライアントからリクエストを投げれば XML で結果が返ってくる。net/http でアクセスするところはまだ作ってない。ていうか、まだ PutAttributes も Query も試してないし。これでバッコンバッコンリクエスト投げたらいくら請求くるんだろう。。誰かやってみたひと居ないかな..

参考:

Tagged with:
2月 25

実は前から公開してたんだけど、最近の機種情報を追加ついで、あと Rails のプラグインを書く勘を取り戻しついでに、ちょっと手を入れたので、改めて紹介しときます。

mbterm_db は Ruby on Rails でケータイサイトをつくる際に、ブラウザのバージョンや画面サイズを取得する Rails プラグインです。

このプラグインは、以前モバイル勉強会で紹介した機種情報 DB の出力の一形式です。機種情報 DB には、基本的に僕が必要なものしか入れてないのですが、最近は FlashLite に傾倒気味なので、そのうち FlashLite のバージョンくらいは入れるかもしれません。

こんなデータベースを持たずとも、ドコモ以外は HTTP リクエストヘッダにそこそこの情報が含まれているのですが、リクエストヘッダの情報は微妙に足りなかったり(一行の文字数とか)、SSL したら取れない事があったりと(SoftBankでたまにある)、結構ハマりがちです。まあ、あったらあったで越したことはないかな、ということで、ご入用の方、どうぞお持ちください。

インストール方法は以下の通り。詳しくは trac の方をご覧ください。jpmobile とか Mobile_on_Rails などのプラグインと併用するのも便利だと思います(使わせていただいてます。感謝! ;-)

$ script/plugin install http://jpmbdb.googlecode.com/svn/trunk/mbterm_db

Continue reading »

Tagged with:
2月 19

Rails や TMail を使った Ruby アプリケーションで携帯メールをさばこうとするとブチ当たる、" 3つ以上連続するドットを含むメールアドレス問題 " の解決方法を再生産したので晒してみます。一応幾つかテストかけて使えてるけど、おかしかったらツッコミください。

まず、TMail::Mail.parse したときのエラーメッセージから:

NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]

これを追っていくと、parser がパースに失敗しているところに行き着く。で、これに対して urekatのスカンク日記3 さんが紹介されているのは、parse 時の Syntax Error を rescue して、「あいまいパース」に落とすエレガントな方法。

プログラマ 福重 伸太朗 〜基本へ帰ろう〜 さんが紹介されているのは、先にアドレスをチェックして、必要に応じて ActionMailer を使わない方法へ回避する、これまたイカした方法。

で、ここで紹介するのは、TMail の parser を書き換えるという方法。
もうちょっと具体的に言うと TMail がメールアドレスのパースに使っている parser.rb – これが Racc というパーサジェネレータで生成されているのだが – の生成元: parser.y を改造してしまう、という方法です。つまり、これをやっちゃうと、同じ稼働環境で動いてるアプリ全体のメールアドレスの parse に影響するので、その辺覚悟してお試しを。

まず、TMail のアーカイブを拾ってきて、以下の通り tmail-1.2.1/lib/tmail/parser.y を書き換える。

$ diff parser.y.org parser.y
211c211,217
< | local_head '.' { val[0].push ''; val[0] }
---
>        | local_head dots
>                 {
>                   val[1].times do
>                     val[0].push ''
>                   end
>                   val[0].push ''
>                 }
235,236c241,242
< dots      : '.'     { 0 }
<             | '.' '.' { 1 }
---
>   dots      : '.'      { @dotnum = 0 }
>             | dots '.' { @dotnum = @dotnum + 1 }

ここで対応したのは、「3 つ以上連続したドット」への対応と、「@ (アットマーク) 直前で連続するドット」への対応の 2 点。(他にもケータイ特有な不可思議なフォーマットがあるかもですが、ここではスルー)

TMail の parser は、ドットふたつには対応していたが、ドット 3 つ以上の場合に対応する生成規則が無い ( dots ‘.’ から dots への還元ができない) ために parse error が起こっていたようだ。

アドレス中の文字列は逐次配列に push され、Address が new されるときに、配列要素の間にドットを入れる (空要素が入っていたら、ドットを一個追加する) という動きをしているようだったので、後半の書き換えで、連続するドットの数をカウントし、local_head への還元時に配列を組み立てるようにした。

前半の書き換えは、local 変数 ( @ の直前) として local_head ‘.’ と、ドットひとつしか許していないようだったので、これを同様に dots 変数を受け付けるようにしたもの。

あとは、こいつを make してやって( make には Racc が必要)、出来上がった parser.rb と parser.y を gem のパスでもどこでも適切なところに置いてやれば OK 。ActionMailer は内部 vendor ライブラリに TMail を包含しているので、必要であれば、そっちも書き換えてやる。(試しに消してみたら、gem の下の TMail を見に行ってくれたみたい。)

この方法のメリットは、サーバ環境を自由に使って良い人なら簡単にできちゃうってこと。デメリットは、これでいいかどうか自信が無いっていうのと、サーバ環境共有してる他のアプリにも影響がおよぶこと、あと、gem update tmail とかやったら元通りになっちゃうってこと。

TMail の過去の修正では、ドット 2 つに対応しているので、RFC 非準拠でもやむなく対応したのかと思っていたが、オリジナルの dots の生成規則を見るに、どうも不本意な実装になっているように見えた。が、この対応方法で合ってるかどうかもよくわからないので、作者さんに連絡する前に、とりあえずここで紹介してみましたです。

Continue reading »

Tagged with:
2月 18

なんと、第27回とのこと。長く続けられている運営の皆様に感謝&尊敬。今回は、霞ヶ関 CTC さんのセミナールームっぽいところをお借りしました。ありがとうございます。

Ruby 関連のこういう勉強会は、今回初めての出席。今回おこなわれた Rails 勉強会は、冒頭、その日のセッションを前後半、幾つかの部屋に分けて募り、いずれかにサインアップしていくという方式。こういう方式のおかげで、Rails 歴の短い僕も、自分のレベルに合うセッションに参加させていただく事ができた。こういう運営はうれしいなあ。

前半は、先日公開された fastladder のソース読み。こういう面白い教材をオープンにしてくれたなかのひとに感謝!一応手元の MacBook で動かせるようにして、gonzui でソース読みの環境を作ってから臨んだ。進行は井上さん。始めに E-R 図で全体のモデルを確認してから、サインアップ〜ユーザ認証〜セッション管理周りを追っていく。認証は AuthenticatedSystem を使ってて、特にトリッキーな部分は無く、素直な実装だった。元が Perl アプリだから当たり前か。Application.rb で before_filter :set_member してて、毎アクセスごとに DB 問い合わせしてユーザの正当性をチェックするような実装になってるみたい。
認証周りだけだと時間が余ってしまったので、lib/crawler.rb も追ってみたい、とお願いし、一緒に読むことになった。サーバサイドだと、クローラの実装周りが面白いところなんじゃないかな、と思って読んでみたけど、こちらもそれほどトリッキーな部分は見当たらなかった。フィードを取得するリクエストの発行部分のタイムアウト値の制御周りや、almost_same みたいなフィードの中身チェックの部分が結構興味深かったかな。本家の方には、まだ明かされてないいろんな工夫があるんだろうな〜。
そうそう、favicon を取得変換する辺りのメモリ使用量について話題になった。僕はこの件なにも追ってなかったんだけど、言われてるような FreeImage の問題なのかな?
メモリ使用量を 10 分の 1 にした shunirr.org さんによれば:

まぁ、favicon取得は新規サイトを登録した時だけだろうと思うので、たぶん2回目以降のくろうるからはメモリ使用量は大して変わらないと思いますけどね。

とのことだけど、どうも update の都度 favicon を見に行ってるように見えるなあ。 (ざっと読んだだけなので、ひょっとしたら違うかも。) subscription のときだけでもいいようにしたら、どうなるかな。
せっかくサーバサイドもセットで公開してくれたんだし、JavaScript 側も含めていろいろいじってみようかな。

後半は、舞波さんによる ActiveScaffold の紹介セッション。去年の8月くらいに ActiveScaffold をちらっと使ってみたけど、カスタマイズの仕方がよくわからなくて、結局放置してた。(ほぼ)ノンカスタマイズで使うときは Streamlined を使っていたので、良い機会だった。
使いはじめが scaffold と同じで簡単なことや、リレーションを動的に解決してくれることは知っていたが、ここまでいろいろカスタマイズできるとは知らなかった。active_scaffold :モデル名 でブロックへ渡してごりごりカスタマイズ。この第一歩がわかっただけで、すげーテンションが上がった。この一歩がわかれば、ドキュメントもソースもどんどん読める!いやー、ActiveScaffold ってスゴいんですね〜。

最後は、KPT (Keep, Problem, Try) と題した、運営の振り返り。前半後半の終わりにも、各セッションでどういうことが話されたかの振り返りの時間があったんだけど、こういうのも含めて、運営がしっかりしてるなあとおもった。27回も続いているのもうなずけます。

いつもブログ拝見してるような方々も来られてて、なんだかとても有意義な時間を過ごさせていただきました。今日は終わってから用事があったので懇親会は行けなかったんだけど、次回は懇親会も行きたいな〜。それから、なんかネタ提供してしゃべれるようにならないと。

Tagged with:
10月 21

今月は、忙殺&ネタ不足で何もできていなかったので、あり合わせで何か作ってみようということで、先に公開した 機種情報 DB の検索サービスを作ってみた。

てなわけで、機種情報検索サービスはこちら

携帯機種名を入れて検索すれば、DB 上のデータを部分一致検索して表示する。そんだけです。

携帯サイトを開発/運用していると、「900 以降だったら横幅何文字で作りゃいいかな?」とか「あれ?この機種横幅いくつだっけ?」とか、機種情報に関するちょっとした調べ物がよく発生するので、自分用に作ってみた次第。http://tmty.jp/mbdb/?m=%s を Firefox にブックマークして、スマートキーワードを適当に設定(たとえば mb とかに)しておけば、<Ctrl+L> => mb n901i => <Enter> てな感じで、ぱぱっと検索できます。

そもそもは、キャリアがバラバラなフォーマットで情報提供するから面倒なんだよな。これから秋冬モデルがババっと出てくるし、適当に DB メンテしてやらねば。

あ、このサービスを携帯サイトの外部連携とかで組込みで使うのはご遠慮ください。そういう Web サービスもあってもいいかな、とは思うけど、今の運用環境的に、こちら側がボトルネックになっちゃうのが間違いないので。あと、レイアウトとか項目もいろいろいじると思いますので、スクレイピングとかするくらいなら 機種情報 DB から CSV 持ってってください。更新は timeline でも拾えますので。それから、ご利用の感想やら、なんかオカシイ動きをしてるところがあったら、コメントとかでこっそり教えてもらえると嬉しいです。

しかし、DB という形でネタを持っておくと、こうやって短時間でいろいろ作れて面白い。冷蔵庫にあるモノで作っちゃいました、という感覚に似てる。いまんとこワンパターンだけど、いろいろ作っておきたいな。

Tagged with: