stompserver の RESTful なインターフェース
前回の続きです。
stompserver に RESTful な口があるようなので今回はそちらを見てみます。
まずは、bin/stompserver を弄ります。
$HTTP_ENABLE をtrue にするだけです。これで、http.rb が読みこまれ、HTTPハンドラが開始されます。
- $HTTP_ENABLE = false + $HTTP_ENABLE = true If $HTTP_ENABLE require 'mongrel' require 'stomp_server/protocols/http' end ... if $HTTP_ENABLE puts "Http protocol handler starting on #{config.opts[:host]} port 8080" EventMachine.start_server(config.opts[:host], 8080, StompServer::Protocols::Http) {|s| s.instance_eval { @@auth_required=stomp.auth_required @@queue_manager=stomp.queue_manager @@topic_manager=stomp.topic_manager @@stompauth = stomp.stompauth } } end
で、stompserver を再起動しましょう。
うまく HTTP ハンドラが動きだしたようです。
% stompserver -p 61613 -b 0.0.0.0 -q file -s .stompfile Queue initialized in /Users/kiwamu/work/temp/stomp/.stompfile TopicManager initialized QueueManager initialized Stomp protocol handler starting on 0.0.0.0 port 61613 Http protocol handler starting on 0.0.0.0 port 8080
深く考えずにブラウザからたたいてみます。
すると、ブラウザに "No messages in queue" と表示されました。
HTTP でメッセージを send するのはさておき、前回の手順で stomp (プロトコル) でつっこんで、同様にブラウザから確認してみると、やはり "No messages in queue"...
たぶん、宛先に設定しているキューの名前を URL にするんだろうなぁと思いつつ、試してみるとちゃんと返ってきました♪
今度はブラウザに "Hello, world!" と表示されています。
もうひとつメッセージを send してから上の URL をたたいてみると、やはり "Hello, world!" とだけ表示されます。
HTTP GET するたびにメッセージを消費しているようですね。
メッセージを新しく send せずにもう一度 URL をたたくと、"No messages in queue" となりました。
ここまできてふと...わざわざブラウザ動かすまでもなかったか、と... (^^;
% irb >> require 'net/http' => [] >> Net::HTTP.version_1_2 => true >> Net::HTTP.start('localhost', 8080) {|http| ?> response = http.get('/queue/test') >> puts response.body >> } No messages in queue => nil
では、HTTP でメッセージを send してみます。
% irb >> require 'net/http' => [] >> Net::HTTP.version_1_2 => true >> Net::HTTP.start('localhost', 8080) {|http| ?> response = http.post('/queue/test', 'Hello, world! from HTTP') >> } => #<Net::HTTPInternalServerError 500 Server Error readbody=true>
あれれ...500 番が返ってきました?
stompserver/protocols/http.rb をながめてみると、HTTP POST ではなく PUT を受けつけるようになっています。つまり、メッセージを send するには HTTP PUT で投げる必要があるとのこと。Web リソースの CRUD って C は POST じゃなかったでしたっけ? ん???
不本意ながら HTTP PUT してみると、ちゃんとメッセージがキューにはいりました。
>> Net::HTTP.start('localhost', 8080) {|http| ?> response = http.put('/queue/test', 'Hello, world! from HTTP') >> } => #<Net::HTTPOK 200 OK readbody=true>
GET してみると、たしかにメッセージがありました。
>> Net::HTTP.start('localhost', 8080) {|http| ?> response = http.get('/queue/test') >> puts response.body >> } Hello, world! from HTTP => nil
Stomp のヘッダー部に載る情報の解析は、現時点では実装されていないものの、HTTP だけでメッセージが送れるってのは使いどころの幅が広がりますね。
AP4R でも今後、RESTful なインターフェースを用意していく予定です。
追記: 2007.11.15
subscribe するのに HTTP GET を使っている点をスルーしてましたが、これも HTTP の仕様としてはおかしいですね。GET ではリソースに対して副作用をもたないはずなので、メッセージを閲覧するだけならともかく、消費してしまうのはまずいです。
ちょっと前に ActiveMQ の REST 対応でも、似たような話題が Paul Winkler さんから指摘されてました。
- rest-discuss : Message queues
http://tech.groups.yahoo.com/group/rest-discuss/message/8955
it's not REST that says GET is a read-only operation; it's HTTP. So
their HTTP implementation is broken. Sadly seems to be pretty common.
DELETE on a URL representing a queue means you want to delete the
entire queue, not a single message!
その結果、ActiveMQ の REST 対応の仕様もこんな感じに変化しているっぽいです。たしかに、上の指摘を受けて変わってきています。
http://activemq.apache.org/rest-protocols.html