2008/09/17


Google App Engineにファイルを転送しようとするとき、ファイルの数が多いと途中で失敗したり時間が掛かったりと結構嫌な思いをする事があったのですが、今日公開されたGAE SDK 1.3にてstaticファイルをZIPでまとめる事が出来る様になりました。
Google App Engine Blog: SDK 1.1.3 Now Available for download

Support for zipimport and a new module, zipserve, which serves static files from a zip archive. These allow you to work past the 1000-file app deployment limit.

The development console now includes a memcache viewer (you can use this by accessing http://localhost:8080/_ah/admin while your app is running on the SDK).

URLFetch now allows users to disable automatically following HTTP redirects.

We now allow composite indexes with repeated properties.

http://googleappengine.blogspot.com/2008/09/sdk-113-now-available-for-download.html
使い方も簡単。まず以下の様な構成のzipファイルを用意します。 Archive:  zippage.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
      289  08/09/17 13:03   index.html
      203  08/09/17 12:53   test.html
     4233  08/01/30 15:55   logo.png
 --------                   -------
     4725                   3 files
そしてアプリケーションハンドラの設定を以下の様に設定します。
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext import zipserve

def main():
  application = webapp.WSGIApplication(
    [
      ('/zippage/(.*)', zipserve.make_zip_handler('zippage.zip')),
    ])
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
もちろんハンドラを分ければ、あるURLではpythonのハンドラ、あるURLではZIP内ファイルという事も出来ます。なお、動いている物はこの辺で確認出来ます。
他にも今回のバージョンアップにて開発者用コンソールにMemcache Viewerが使える様になりました。
gae-memcache-viewer
直接値を編集する事も出来ますが、現状マルチバイト文字でエラーが出ているようです。
他、URLFetchでURLの自動フォローを出来ないようになったり等の修正も行われています。

話は変わって、tokuhiromさん作のjavascript v8エンジンで動くCGIインタフェースllv8callですが、tokuhiromさんが入れ込んでる機能をwin32に移植して行っていますがlibmemcachedのwin32版がMSVCでビルド出来なかったので、自前でmemcacehdとお喋りする様にしました。興味がある方はこの辺のソースをご覧下さい。

Posted at by



2008/09/11


ちょっと訳あって、WScriptからjQueryを呼び出す必要があり(嘘です)作ってみました。

これを使うと $.each([1,2,3], function(index, item) {
    print("foo" + item);
});
$.ajax({
    type: "GET",
    url: "http://www.google.co.jp/",
    async: false,
    success: function(data) {
        print(data);
    }
});
こんなソースが実行出来ます。
$.eachなんかは目茶目茶便利なので、使わない手はありません。とりあえず、$.ajaxでgoogle.co.jpのソースが取得出来るくらいは動きます。
以下全体ソース。
// vim:fdm=marker fdl=0 fdc=0 fdo+=jump,search:
// vim:fdt=substitute(getline(v\:foldstart),'\\(.\*\\){\\{3}','\\1',''):
// {{{
(function(target) {
    target.window = {
        document : {
            defaultView : {}
        },
        navigator : {
            userAgent : "Windows Scripting Host"
        },
        location : {},
        XMLHttpRequest : function() {
            // copied from http://la.ma.la/misc/js/ie_xmlhttp.js
            var self = this;
            var props = "readyState,responseText,responseXML,status,statusText".split(",");
            this.readyState  = 0;
            this.__request__ = new ActiveXObject("Microsoft.XMLHTTP");
            this.__request__.onreadystatechange = function(){
                for(var i=0;i<props.length;i++){
                    try{
                        self[props[i]] = self.__request__[props[i]]
                    }catch(e){
                    }
                }
                self.onreadystatechange()
                if(self.readyState == 4) self.onload();
            }
            this.onreadystatechange = function(){};
        },
        setInterval : function(func, interval) {
            func(); // quickly f*ckin hack
        },
        clearInterval : function(timer) {
        },
        setTimeout : function(func, interval) {
            func(); // quickly f*ckin hack
        },
        clearTimeout : function(timer) {
        }
    };
    var methods = "open','abort','send','setRequestHeader','getResponseHeader','getAllResponseHeaders".split("','");
    var make_method = function(name){
        window.XMLHttpRequest.prototype[name] = function(){
            var params = new Array(arguments.length);
            for(var i=0;i<params.length;i++) params[i] = "_"+i;
            return Function(
                params.join(","),
                ["return this.__request__.",name,"(",params.join(","),")"].join("")
            ).apply(this,arguments);
        }
    };
    for (var i=0;i<methods.length;i++) make_method(methods[i]);
    for (var n in window) target[n] = window[n];
})(this);

function print(msg) {
    WScript.StdOut.WriteLine(String(msg));
}

function require(source, target) {
    target = target||this;
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    var stm = fso.OpenTextFile(source, 1, false, -2);
    var text = stm.ReadAll();
    stm.Close();
    eval(text, target);
    for (var n in windowif (typeof target[n] === 'undefined') target[n] = window[n];
}
// }}}

require("jquery-latest.js");

$.each([1,2,3], function(index, item) {
    print("foo" + item);
});

$.ajax({
    type: "GET",
    url: "http://www.google.co.jp/",
    async: false,
    success: function(data) {
        print(data);
    }
});
setTimeoutとかsetIntervalはf*ckingはhackなので$.get(非同期)は動きません。直す余地ありです。
あと、XMLHttpRequestのbindはmalaさんのをパクってます。
Posted at by




tokuhiromさん作のfcgi-v8をCGIインタプリタとして、cho45さん作のblosxom.rhinoを改造してblosxom.v8というのを作ってみた。
v8にはunevalが無かったのでdankogaiさん作のuneval.jsを使わせて頂いた。
実行画面はblosxom.rhinoの書き換えなので、パクリ気味ですが...
blosxom-v8
fcgi-v8でファイル日付の取得が実装出来ていないので、今は日付は表示されていません。
blosxom.v8
よかったら遊んでみて下さい。
Posted at by