最近全然触っていなかったGoogle App Engine。
今月初旬にリリースした1.4.0からChannel APIというのが使えるようになってリアルタイムWebアプリが出来るらしい、ということなのでちょっと触ってみた。
Channel Python API Overview | Python | Google Cloud Platform
#!/usr/bin/env python from google.appengine.api import channel from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext.webapp import util class MainPage(webapp.RequestHandler): def get(self): user = users.get_current_user() if not user: self.redirect(users.create_login_url(self.request.uri)) return token = channel.create_channel('hoge') template_values = { 'token': token, } self.response.out.write(template.render('index.html', template_values)) class PostPage(webapp.RequestHandler): def post(self): user = users.get_current_user() channel.send_message('hoge', self.request.body) self.response.out.write('hoge') class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('Hello world!') def main(): application = webapp.WSGIApplication([ ('/', MainHandler), ('/mainpage', MainPage), ('/post', PostPage), ], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()
client_idはとりあえず固定で 指定したURLに繋いでいるものすべてが共通で使うようにしてみた
<html> <head> <title>Channel API</title> <script type="text/javascript" src="/_ah/channel/jsapi"></script> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript">google.load("jquery", "1.4.4");</script> <script type="text/javascript" src="/static/channel.js"></script> <link href="/static/style.css" rel="stylesheet" type="text/css"> </head> <body> <form id="message" action="" method="POST"> <input id="token" type="hidden" name="token" value="{{ token }}" /> <input id="text" name="message" type="text" /> <input type="submit" /> </form> <hr /> <dl id="list"></dl> </body> </html>
"/_ah/channel/jsapi"ってところにclient側で必要なものが詰まっているようで、サーバー側で生成したtokenを使ってJS側でgoog.appengine.Channelをnewすると、Web Socket的なものが共通なインターフェースで使えるようになるっぽい。
$(function() { var token = $('#token').attr('value'); var sendMessage = function(data) { $.ajax({ url : '/post', type: 'POST', data: data }) }; $('#message').submit(function() { sendMessage($('#text').attr('value')); return false; }); channel = new goog.appengine.Channel(token); socket = channel.open(); socket.onopen = function() { console.log('open'); }; socket.onmessage = function(msg) { var date = new Date(); $('#list').prepend($('<dt>' + date + '</dt><dd>' + msg['data'] + '</dt>')); }; socket.onerror = function() { console.log('error'); }; socket.onclose = function() { console.log('close'); }; });
POSTされたものをmessageとして送信するようにしてみた。
片方でsubmitしたものがほぼリアルタイムでもう片方で更新される…!
メモ
どうやら、ローカル環境(dev_appserver.py)で動かしているときは1秒ごとにgetしまくっているみたい。本番環境にあげたらそんなことはなかった。web socketを使っているのか comet的なものなのかはよく調べてないので分からない。ブラウザによって切り替えたりしてくれてるのかな…?
実装が悪いだけかもしれないけど、繋がっているはずなのにうまくデータがpushされてこなかったり、ということがあった。
パフォーマンスはどんなもんなんだろう。node.jsとかが面白そうなので触ってみたいけど(まだ触れていない…)、これで十分に出来ること、っていうのもあるのかもしれない。