Posts tagged ‘Google App Engine’

GAE のアプリケーションを Marketplace に登録するときの注意点

Google Apps Marketplace にアプリケーションを登録しようとしてハマった。この Marketplace への登録についてはそれなりにドキュメントが揃っているのですぐに出来るだろうと思っていたが、かなり時間が掛かってしまったのでその経過をメモ。

まずは Marketplace のデベロッパ登録をするのだが、これについてはオリジナルの “Google Apps Developer Program Site” に加えて、”Google Apps Marketplaceにアプリケーションを登録する方法” や “Google Apps Marketplaceにアプリを公開するときに気をつけること” を参考にさせていただいた。これらのドキュメントにしたがって、Marketplace の Vendor 登録はあっさりと完了。

続いてサンプルアプリケーションを登録してみようということで、”Writing your First Marketplace App using Python” に掲載されているコードを使って、Google App Engine にアプリケーション環境を構築する。そしてこれを Marketplace に登録し、さらに Google Apps からアクセスできることを確認した。

本来はここで Google Apps のアカウントからアプリケーションを起動できるはずなのだが、どうしてもエラーとなってしまい期待した結果にならない。調べてみるとサンプルコードの federated_identity() が本来返すべき値を返さず None を返していることがわかった。OpenID まわりでうまく行ってないのだろうと推測するものの、どうすればいいのか分からないまま調べを進めていたら、”App Engine and Chrome Webstore Issues” に解決策があった。原因はアプリケーションではなく GAE の設定であった。GAE の Application Settings にある Authentication Options を (Experimental) Federated Login にすることで、Google Apps に組み込んだ自前のアプリケーションを動作させることができた。

結論:
Google Marketplace に登録するアプリケーションを Google App Engine 環境で提供するときは GAE の Authentication Options を変更する必要あり。

Google App Engine 超入門

知人の会社で実施している社内向けのミニセミナーに講師として呼ばれた。どんな話題でもよい、ということだったので、Google App Engine の概略を解説することにした。1時間という貴重な時間を割いて集まっていただいた皆さんに満足してもらえる内容だったかどうか不安が残る。とりあえずその時に使った資料を次の URL で公開しておく。

http://bit.ly/9b2bwx

終盤の Google Apps との連携部分についてはうまく説明出来なかったので、十分に理解してもらえなかったかもしれない。

Google Apps と独自のホームページ

Google 社が無償提供している Google Apps の Standard Edition は、一般企業だけでなく NPO や NGO のような組織体、同窓会や趣味のサークル団体などでも利用すれば、メンバー間のコミュニケーションを活性化するだけでなく、事務作業のコストと時間を大幅に節約できる可能性がある。

Google Apps では独自のドメインを使って Gmail やカレンダー、Docs などの機能を利用できる。また、シンプルながらも良く出来た CMS である「サイト」機能を使えば、手軽にホームページを公開することができる。しかし、この「サイト」は誰にでも使いやすい反面、凝ったデザインのホームページや CGI のような Web アプリケーション的要素が少しでも入ったホームページの制作は困難である。そのためせっかく Google Apps を使いながらも、ホームページ公開だけのために別の Web サーバが必要になるかもしれない。

これではもったいないので、Google Apps の環境でも従来のように自由にホームページを公開するため、Google App Engine (GAE)を利用する方法を考えてみた。app.yaml ファイルを static_files や static_dir のような静的ハンドラだけで定義してしまうやり方である。

例えば top_dir ディレクトリを GAE 用アプリケーションのトップディレクトリとして、HTML ファイルやイメージファイルなどを次のように配置したとする。

top_dir/app.yaml
top_dir/static_dir/img/logo.png など
top_dir/static_dir/index.html など

この例の場合であれば app.yaml を次のよう定義する。

application: your-app-id
version: 1
runtime: python
api_version: 1

handlers:

– url: /img
  static_dir: static_dir/img

– url: /
  static_files: static_dir/index.html
  upload: static_dir/index.html

– url: /(.*)
  static_files: static_dir/\1
  upload: static_dir/(.*)

このようにしてから appcfg.py update top_dir コマンドを実行すれば、HTML ファイルなどがデプロイされる。あらかじめ Python と GAE SDK がインストールされていれば、GAE のことを意識せずに ftp のような感覚でファイルの更新ができると思う。この場合 Python は appcfg.py コマンドを実行するためだけに使われる。

デプロイしたものに your-app-id.appspot.com でアクセスできることを確認したら、Google Apps のダッシュボードで GAE アプリケーションを追加して適当な URL を割り振れば、Google Apps 環境だけで自由なデザインのホームページを公開することができる。

実際にこのやり方で作ってみたのが次のページ。ここでは teshigoto-lab.net というドメインで Google Apps を利用している。

Google Apps を使ってみよう!(http://www.teshigoto-lab.net/)

ちなみに同じようなページを Google Apps 標準の「サイト」機能でも作ってみた。こちらは favicon.ico が Google Apps オリジナルデザインのものになっている。

「サイト」版 Google Apps を使ってみよう!(http://google-apps.teshigoto-lab.net/)

「サイト」版は途中で面倒になってしまい、スタイル適用や画像ファイルへのリンク設定をしていない。したがって実際はもう少しまともなデザインにすることができるはずだ。

このサンプルページのようにシンプルなデザインであれば「サイト」機能だけでも何とか出来そうだが、もっと凝ったものになってくると GAE を使ったほうが楽だろうと思う。また、GAE には履歴管理機能があるので、これを使って複数リビジョンのホームページを簡単に切り替える、といったことも可能になる。

ところで最近、Google 社のサイトにおいて Standard Edition 用の申込み画面を見つけるのが極めて困難になっている。以前はそれほど深くない階層のところに他の Edition との機能比較表が掲載されていて、そこから簡単に申込み画面へ行き着けたのだが、その比較表は見つけられなくなってしまった。現状ではあたかも有料の Premium Edition しか存在しないように見える作りになっていて、一旦は Premium Edition の申込みボタンを押してからでないと Standard Edition の申込み画面に行き着けないようだ。

恐らく Premium Edition に比重を移して、Standard Edition は廃止の方向に持って行くつもりなのだろう。それは仕方がないことだと思う。しかし機能制限があっても構わないので、Standad Edition よりも安価(2,000円/1アカウント・1年くらいか?)な Edition も用意してもらえるとうれしい。

Google App Engine 用のログイン認証機能を作ってみた

Google App Engine では Google アカウントの認証機能がそのまま利用できるので、ログイン管理の手間が掛からない。しかし、当然のことながらアプリケーションの利用者は Google アカウント保持者に限定されてしまうし、逆に何も制限を加えないと Google アカウント保持者は誰でもアクセスできてしまうことになる。

そこで Google アカウントとは無関係にアカウントを管理する仕掛けのひな形を作ってみた。サンプルは http://teshigoto-showcase-02.appspot.com/ で実際に稼働している。ここで新規登録を行えばアカウントを取得することができるが、試用アカウントを使えば新規登録しなくてもログインすることができる。試用アカウントはサンプルサイトのトップページに記載してある。また、ソースコードは http://www.teshigoto.net/showcase.html の「Another Loin Utility – GAE case study 2」に置いた。

アカウントの新規登録を行うとき、同一ログイン名の同時登録を避けるため、ファイルを使ったロック処理を行おうとしたが、Google App Engine では肝心の fcntl を利用できない。そこで今回は登録依頼のあったアカウントを無条件に Datastore に格納してしまい、その後改めて同一のログイン名による検索を行って複数のエンティティが見つかったときは、自分自身を削除して「同じログイン名がすでに登録されてます」メッセージを出す、という手順にしてみた。具体的には次のような感じ。

new_user = users.Users(id = new_login_id, ...)
new_user.put()

query = users.Users.all()
query.filter('id =', new_login_id)

count = 0
for user in query:
    count += 1

if count == 1:
    #  regist copleted
    pass
else:
    # duplicated id
    new_user.delete()

このやり方だと同じログイン名を同時に登録しようとして、どちらも失敗する可能性が残るが、一般的なログイン名ではそれでも構わないだろうと判断した。

ログインすればセッション管理も必要になるので、これも作ってみた。前回公開したサンプルでもセッション管理を作ったものの中途半端だったので、もう少し手を入れてみた。セッション ID を Cookie として送信するために準備する機能(送信そのものは画面表示モジュールが行うことになる)や、セッション継続時に保存しておくデータを Datasore に格納する機能などがある。

import os
import re
import time
import random
import hashlib

from google.appengine.ext import db


class SessionDb(db.Expando):
    sid = db.StringProperty()


DEFAULT_SID_NAME = 'alu_001'

class Session():

    def __init__(self, req, res, sid_name=DEFAULT_SID_NAME):
        self.sid_name = sid_name
        self.req = req
        self.res = res
        if sid_name in req.cookies:
            self.sid_value = req.cookies[sid_name]
        else:
            self.sid_value = ''

    def new_ssn(self, ssl=False):
        random.seed()
        random_str = str(random.random()) + str(random.random())
        random_str = random_str + str(time.time())
        random_str = random_str + os.environ['REMOTE_ADDR']

        self.sid_value = hashlib.sha256(random_str).hexdigest()

        cookie_val = self.sid_name + '=' + self.sid_value
        if ssl:
            cookie_val += ';secure'

        self.res.headers.add_header('Set-Cookie', cookie_val)

        ssn_db = SessionDb(sid=self.sid_value)
        ssn_db.put()

    def destroy_ssn(self):
        ssn_db = SessionDb.all()
        ssn_db.filter('sid =', self.sid_value)
        ssn = ssn_db.fetch(1)
        db.delete(ssn)

        expires = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", time.gmtime(0))
        cookie_val = self.sid_name + '=null' + ';expires=' + expires
        self.res.headers.add_header('Set-Cookie', cookie_val)

    def get_ssn_data(self, k):
        ssn_db = SessionDb.all()
        ssn_db.filter('sid =', self.sid_value)
        ssn = ssn_db.fetch(1)

        return ssn[0]._dynamic_properties[k]

    def set_ssn_data(self, k, v):
        ssn_db = SessionDb.all()
        ssn_db.filter('sid =', self.sid_value)
        ssn = ssn_db.fetch(1)
        ssn[0]._dynamic_properties[k] = v

        ssn[0].put()

    def chk_ssn(self):
        ssn_db = SessionDb.all()
        ssn_db.filter('sid =', self.sid_value)
        count = 0
        for i in ssn_db:
            count += 1

        if count == 1:
            return True
        else:
            return False

さらに、今回のサンプルでも多言語対応を試みた。前回はオリジナルのちょっと安直な方法で実装したが、今回は gettext を利用してみた。これによって言語リソースを完全に Python のソースコードと分離することができた。また、表示言語を固定せずに、利用者からの指示で動的に言語を切り替えられるようにした。具体的には Python ライブラリリファレンス「6.28 gettext — 多言語対応に関する国際化サービス」を参考にしながら、おおよそ次のような流れで処理を行っている。

locale_path = os.path.dirname(__file__) + '/../locale'   # リソースファイルを置いた場所
supported_lang = ['ja', 'en']    # サポートする言語の一覧
for lang_name in self.supported_lang:
    lang[lang_name] = gettext.translation('resource', locale_path, languages=[lang_name])

accept_lang = 'ja'   # 実際の表示言語をここで指定
lang[accept_lang].install()
_ = lang[accept_lang].gettext

print _('message_sentence')    # 指定した言語で表示される

Google App Engine のサンプルプログラム

遅ればせながら Google App Engine のサンプルプログラムを作ってみた。簡単なアドレス帳のようなもので、Google App Engine のサイトにあるチュートリアルと同程度のものである。画面インタフェースはきわめて質素で CSS や JavaScript はほとんど使っていない。ただ、本格的なアプリケーションを作ろうとするときのテンプレートとしても利用できるようファイル分割に考慮した。また、簡単なセッション管理機能と多言語対応機能も試作してみた。

Google サーバのここ( http://teshigoto-showcase-01.appspot.com/ )で実際に試用することができる。ただしログイン認証のために Google アカウントが必要である。またソースコードはここ( http://www.teshigoto.net/showcase.html )に置いてある。

次はもう少し実践的で実運用にも耐えるようなものを作ってみたい。