MongoDBとApacheだけでCGIを作ることは可能でしょうか?


挑戦してみたのですが、どうしてもやり方がわかりませんでした。
http://dqn.sakusakutto.jp/2012/05/apache_mongodbshell_javascript_cgi.html

ご教授のほど、よろしくお願いいたします。

回答の条件
  • URL必須
  • 1人5回まで
  • 登録:
  • 終了:2012/06/03 16:35:19
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:TransFreeBSD No.2

回答回数668ベストアンサー獲得回数268

ポイント50pt

おもしろそうですね。
CGIだと動作自体は重そうですが、DBの内容をJSONで出力するような用途なら簡単な記述で済みそうです。

で、本題ですが、やはり環境変数に関するものは無さそうです。なのでラッパー書いてみました。
環境変数は--evalオプションつかって、変数ENVに代入してます。
POSTの内容はENV.POSTに入れました。通常1行だと思いますが複数行であれば「;」でつなげています。
また、コマンドラインに入れる関係上、最大長が気になるのでとりあえず3,000バイトを制限値にしてます。これは--evalやめてファイル経由にすれば解決はしますが手抜きしました。
あと、環境変数に複数行入っている事は考慮してません。多分エラーにならず無視というか、ENVのキー扱いになるだけのはずです。SERVER_SIGNATUREとか複数行の事がある様な気がしてますが、多分使わないだろうから手抜きしました。
POSTやQUERY_STRINGは自前でパースすることになります。

と書いてみたものの、正直安全面は、エスケープとか充分なのか分かりません。
実用的にはperlとかで既存のライブラリ使ってJSONにした方が安全なのでしょうけれど、それやっちゃうとMongoDBのCGIなのと言う疑惑がw
#shやsedは良いのか?というと広い意味でOSの一部ということで。perlも微妙だけれど。
MongoDB自体で環境変数や標準入力に対応してもらえば一番なのでしょうけれど。

mongowrapper

#!/bin/sh
env='POST:"'
if [ "0$CONTENT_LENGTH" -lt 3000 ]; then
    env=$env`sed -e 's/[[:cntrl:]]//;s/["\\\\]/\\\\&/g;1h;1!H;${g;s/\n/;/g;p;};d'`
fi
env=$env'"'
env=$env`printenv | sed -e 's/[[:cntrl:]]//;s/["\\\\]/\\\\&/g;s/^/"/;s/=/":"/;s/$/"/;H;${g;s/\n/,/g;p;};d'`
/usr/local/bin/mongo --quiet --eval "var ENV={$env}" "$1"

呼び出しはこんな感じで。
#env付けないとエラーになるのは何でだっけ?

#!/usr/bin/env /path/to/hoge/mongowrapper
print("Content-type:text/plain\n");
print("ENV=");
printjson(ENV);

最後に。
このラッパーは引数を一つしか見ません。
ブログの方で、"?foo"を付けるとエラーメッセージ出るのはCGIの仕様
http://ja.wikipedia.org/wiki/Common_Gateway_Interface

QUERY_STRINGに文字'='が含まれない場合は、サーバはQUERY_STRINGの内容をコマンドライン引数としてCGIプログラムに渡す。

でMongoDBshellの引数として付いた"foo"をスクリプトファイルとして解釈するからだと思います。なので引数1つにしました。
#本当は引数チェックしてスイッチとか渡せばいいけれどこれも手抜き。

id:DQNEO

なるほど!!
その発想はなかったです。
shを経由すればよかったんですね。
あと、PerlのCGIをかませばいろいろできそうですね!
ありがとうございます!

2012/05/28 01:21:33
id:a-kuma3

#env付けないとエラーになるのは何でだっけ?

シェバングは再帰的に解釈されないから、コマンドにスクリプトが指定できない。
# じゃなかったっけ。

2012/06/02 15:50:03

その他の回答1件)

id:oil999 No.1

回答回数1728ベストアンサー獲得回数320

ポイント50pt

MongoDBはデータベースなので、CGIは実装できません。
http://www.mongodb.org/

id:DQNEO

正確に言うとmongoDBshell です。(javascript実行環境)
hello worldは動きました。

2012/05/28 01:09:56
id:TransFreeBSD No.2

回答回数668ベストアンサー獲得回数268ここでベストアンサー

ポイント50pt

おもしろそうですね。
CGIだと動作自体は重そうですが、DBの内容をJSONで出力するような用途なら簡単な記述で済みそうです。

で、本題ですが、やはり環境変数に関するものは無さそうです。なのでラッパー書いてみました。
環境変数は--evalオプションつかって、変数ENVに代入してます。
POSTの内容はENV.POSTに入れました。通常1行だと思いますが複数行であれば「;」でつなげています。
また、コマンドラインに入れる関係上、最大長が気になるのでとりあえず3,000バイトを制限値にしてます。これは--evalやめてファイル経由にすれば解決はしますが手抜きしました。
あと、環境変数に複数行入っている事は考慮してません。多分エラーにならず無視というか、ENVのキー扱いになるだけのはずです。SERVER_SIGNATUREとか複数行の事がある様な気がしてますが、多分使わないだろうから手抜きしました。
POSTやQUERY_STRINGは自前でパースすることになります。

と書いてみたものの、正直安全面は、エスケープとか充分なのか分かりません。
実用的にはperlとかで既存のライブラリ使ってJSONにした方が安全なのでしょうけれど、それやっちゃうとMongoDBのCGIなのと言う疑惑がw
#shやsedは良いのか?というと広い意味でOSの一部ということで。perlも微妙だけれど。
MongoDB自体で環境変数や標準入力に対応してもらえば一番なのでしょうけれど。

mongowrapper

#!/bin/sh
env='POST:"'
if [ "0$CONTENT_LENGTH" -lt 3000 ]; then
    env=$env`sed -e 's/[[:cntrl:]]//;s/["\\\\]/\\\\&/g;1h;1!H;${g;s/\n/;/g;p;};d'`
fi
env=$env'"'
env=$env`printenv | sed -e 's/[[:cntrl:]]//;s/["\\\\]/\\\\&/g;s/^/"/;s/=/":"/;s/$/"/;H;${g;s/\n/,/g;p;};d'`
/usr/local/bin/mongo --quiet --eval "var ENV={$env}" "$1"

呼び出しはこんな感じで。
#env付けないとエラーになるのは何でだっけ?

#!/usr/bin/env /path/to/hoge/mongowrapper
print("Content-type:text/plain\n");
print("ENV=");
printjson(ENV);

最後に。
このラッパーは引数を一つしか見ません。
ブログの方で、"?foo"を付けるとエラーメッセージ出るのはCGIの仕様
http://ja.wikipedia.org/wiki/Common_Gateway_Interface

QUERY_STRINGに文字'='が含まれない場合は、サーバはQUERY_STRINGの内容をコマンドライン引数としてCGIプログラムに渡す。

でMongoDBshellの引数として付いた"foo"をスクリプトファイルとして解釈するからだと思います。なので引数1つにしました。
#本当は引数チェックしてスイッチとか渡せばいいけれどこれも手抜き。

id:DQNEO

なるほど!!
その発想はなかったです。
shを経由すればよかったんですね。
あと、PerlのCGIをかませばいろいろできそうですね!
ありがとうございます!

2012/05/28 01:21:33
id:a-kuma3

#env付けないとエラーになるのは何でだっけ?

シェバングは再帰的に解釈されないから、コマンドにスクリプトが指定できない。
# じゃなかったっけ。

2012/06/02 15:50:03

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません