CGI を動かす (GmCapsule・ステータスコード)
動的処理を行う場合は CGI を使用します。
Web では初期の頃(主に 1900 年代)に使用されていて、
PHP が普及する前に主にシェルや Perl を用いて処理されていました。
近いような事が Gemini プロトコルでも可能です。
CGI として動作可能であれば、プログラミング言語は問いません。
このページでは GmCapsule を用いて CGI を動作する環境を構築しています。
GmCapsule は Python で作られていて、
公式ドキュメントなども CGI サンプルが Python になっているのですが、
実際には Python 以外でも動作が可能です。
このページでは多くの環境で動作する sh にしています。
関連資料として、次をリンクします。
Twins | MakerSpace (https:)
gemini cgi guide | tilde.team wiki (https:)
Gemini: background | Zen (attitude) (https:)
About gemini markup and gmnisrv | Remy Noulin's Blog (https:)
上の一部リンクで触れられている gmnisrv は CGI 動作対応 Gemini サーバーの一つで、
C 言語で作られていて、より多くの環境でビルドしやすいと思われますが、
2023 年の更新を最後にメンてナンスしない事が明記されているので、
ここでは触れません。
https://git.sr.ht/~sircmpwn/gmnisrv/
- - - 🎈 - - -
GmCapsule の初期設定
ここではローカルで環境を整える前提で記載をしています。
Python が入っている前提で pip でインストールを行います。
入った事を確認します。
設定ファイルは .ini で制作します。
ここでは localhost.ini とします。
[server]
host = localhost
certs = ./certs
[static]
root = .
[cgi]
bin_root = ./cgi-bin
各場所は相対的にもできます。上記の場合、次の記載となります。
# Configuration | GmCapsule User manual
.ini の項目追加でポート番号の指定、サーバーレベルでの rewrite (転送)、
CGI のエントリポイント、Git リポジトリの表示など、
GmCapsule はいろいろ対応しています。
localhost.ini
localhost/
index.gmi
cgi-bin/
localhost/
hello
certs/
localhost/
cert.pem
key.pem
記載の中で host = localhost はネット上に公開する場合
host = example.com sub.example.com という感じに複数のホスト名を記載できます。
この場合各場所にある localhost が各ホスト名で参照される事になります。
GmCapsule では証明書が必要ですので、作成します。.pem 形式である必要があります。
以下では期限を約 1000 年にしてあります。
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
-days 365000 -nodes -subj "/CN=localhost"
日数の代わりに期限日時を指定する方法もあります。
9999年12月31日23時59分59秒を期限とする場合は次のとおりです。
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
-not_after 99991231235959 -nodes -subj "/CN=localhost"
Agate だと .der 形式が使われているので .pem 形式への変換が必要です。
openssl x509 -inform der -in cert.der -outform pem -out cert.pem
openssl pkey -inform der -in key.der -outform pem -out key.pem
.pem 形式はテキストエディタで開くと
-----BEGIN CERTIFICATE----- や -----BEGIN PRIVATE KEY----- ではじまる
テキストファイルになっています。
.der はバイナリーファイルなので文字化けした内容になっています。
それでは、cgi-bin/localhost/hello のテキストファイルを作成します。
GmCapsule で bin_root を用いている場合、
cgi-bin 下を動的ファイルの対象とするため、
拡張子を .cgi にする必要はありません。
#!/bin/sh
printf '20 text/gemini\r\n'
printf 'Hello CGI!\r\n'
ステータスコード 2 桁の後に出力する MIME type を指定します。
正常な場合は 20 です。(http・https でいう 200 に同等)
Gemtext ならば text/gemini です。
http・https 同様に文字コードも入れられますが、
通常は UTF-8 で扱うので、UTF-8 で記載されてあれば通常考慮する必要ありません。
この hello ファイルには実行権限をつけておいて下さい。
それではサーバーを起動してみます。
gmcapsuled -c localhost.ini
エラーが出ている場合は場所やファイルを確認してみて下さい。
正常に起動しているなら Lagrange などの Gemini クライアントを起動し、
gemini://localhost/ で localhost/index.gmi の静的ファイル、
gemini://localhost/hello で cgi-bin/localhost/hello で作成した
CGI が動作している事を確認します。(cgi-bin は不要です)
ファイル名を省略した URL で localhost/index.gmi の代わりに CGI を動作させたい場合、
cgi-bin/localhost/index.gmi を作成します。
- - - 🎈 - - -
CGI のサンプル
ここでは多くの環境で動作できるように sh を使用しています。
hello
20 を出力し、gemini 形式(Gemtext)でメッセージを出力します。
#!/bin/sh
printf '20 text/gemini\r\n'
printf 'Hello CGI!\r\n'
入力フォームを表示します。入力結果は URL の ? 以下に入ります。
多くの CGI 対応 Gemini サーバーでは QUERY_STRING で内容を取り出せます。
#!/bin/sh
[ "${QUERY_STRING:+dummy}" ] || {
printf '10 Please enter your name\r\n'
exit
}
printf '20 text/gemini\r\n'
echo "hello, $QUERY_STRING"
QUERY_STRING は URL エンコードされた状態なので、
日本語などは文字列が変換されています。(例: 風船 → %E9%A2%A8%E8%88%B9 )
そのため通常は URL デコードをする必要があります。
URL に含まれる仕様なので、文字数には制限があり、
日本語は 100 文字前後になります。
この問題を回避する方法として Titan プロトコルが存在します。
env
環境変数の値を一覧表示します。
#!/bin/sh
printf '20 text/gemini\r\n'
echo "ENV"
printenv
GmCapsule は動作しているサーバーの環境変数も引き継いでいるため、
けっこう多くの値が入っている事がわかります。
redirect
転送はこのように転送先 URL を入れますが、相対的な場所でも良い事になっています。
#!/bin/sh
printf '30 gemini://geminiprotocol.net/\r\n'
上は gemini: にしていますが、もちろん https: は他のプロトコルも有効です。
pass
http の BASIC 認証みたいなもの。パスワードを知ってる人だけが参照できます。
パスワード入力向けのコードがあり、
クライアントは文字を表示しないようにしてくれる事を期待できます。
Gemini プロトコルは SSL で暗号化も行われています。
#!/bin/sh
PASS="password"
if [ "${QUERY_STRING}" != "${PASS}" ]
then
printf '11 Please enter password\r\n'
exit
fi
printf '20 text/gemini\r\n'
echo "hello!"
ssl
認証を SSL 証明書で行います。
env を実行して証明書を適用すると TLS_CLIENT_HASH にハッシュ値を得られます。
これを HASH の値として入れて下さい。この証明書を持つ人だけが参照できます。
!/bin/sh
HASH="ハッシュ値"
if [ "${TLS_CLIENT_HASH}" != "${HASH}" ]
then
printf '60 This page is only available to those with the appropriate certificates.\r\n'
exit
fi
printf '20 text/gemini\r\n'
echo "hello!"
titan,titan
GmCapsule は Titan プロトコルにも対応していて、
CGI で受け取ったテキスト・ファイルを処理できます。
Titan プロトコルは ファイル,titan を作成します。
. (ドット・ビリオド) ではなく , (コンマ) なのにご注意下さい。
この CGI の実行は例えば titan://localhost/titan となります。
#!/bin/sh
STDIN=$(cat)
printf '20 text/gemini\r\n'
echo "Client cert hashes: $REMOTE_IDENT"
echo "Titan token: $TITAN_TOKEN"
echo "File size: ${#STDIN} bytes"
- - - 🎈 - - -
ステータスコード
HTTP・HTTPS では 3 桁のコードを返しますが、Gemini は 2 桁になっています。
詳しいコードの説明は次を参照して下さい。
gemini://geminiprotocol.net/docs/protocol-specification.gmi
1● 入力を必要
入力を促すフォームの表示はステータスコードで行います。
- 10 INPUT - 入力フォームを表示
- 11 SENSITIVE INPUT - パスワードなどの入力。クライアントは入力文字を隠すでしょう
2● 成功
HTTP は通常 200 なのでわかりやすいです。
- 20 SUCCESS - Gemtext などを返す
3● リダイレクト
HTTP は 30● なので、これもわかりやすいですが、並びに注意して下さい。
- 30 REDIRECT - TEMPORARY - 一時的な転送。メンテ中など
- 31 REDIRECT - PERMANENT - 恒久な転送。新たな URL に返送した場合など
4● 一時的な故障
http・https で 50● を返すエラーは Gemini では 4● で返す事が多そうです。
- 40 TEMPORARY FAILURE - 一時的に問題が発生している場合
- 41 SERVER UNAVAILABLE - 一時的なサーバーエラーなど
- 42 CGI ERROR - CGI を処理してのエラー
- 43 PROXY ERROR - プロキシ関連のエラー
- 44 SLOW DOWN - サーバーからレスポンスが得られないなど
5● 永続的な故障
http・https だと Not Found は 404 ですが、Gemini は 51 になっています。
同様に Gone も http・https は 410 ですが、Gemini は 52 です。
- 50 PERMANENT FAILURE - サーバーのハード故障など、41 より重い状況
- 51 NOT FOUND - ファイルが存在しない場合
- 52 GONE - このサーバー・ドメインで提供を終了している
- 53 PROXY REQUEST REFUSED - プロキシが Gemini プロトコルを提供していない場合など
- 59 BAD REQUEST - リクエストされた形式が不定など
6● クライアント証明書
ステータスコードで定義されていますが、通常はクライアントが返すでしょう。
- 60 CLIENT CERTIFICATE REQUIRED - クライアント証明書の要求を行う場合
- 61 CERTIFICATE NOT AUTHORISED - 証明書未承認。他用途の証明書を使用した場合
- 62 CERTIFICATE NOT VALID - 証明書は無効。証明書の期限切れなど
- - - 🎈 - - -
🎈 fusen.srht.site
- - - 🎈 - - -
😺 Powered by nya.je