それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

任意の拡張子(.jpg/.zip/.ico) をApacheHandlerでcgi/php処理する

ブラウザでURL画像をクリックしたら、php起動したい

画像のURLをクリックすると、WEBサーバから画像が送信される。当たり前のことですが、この当たり前の処理に、ハンドラを加えてプログラムを追加したいと思います。

http://example.com/img/top_banner.jpg

通常処理の場合

WEBサーバーは次の処理をする。

  1. URLにリクエスト来る
  2. URL からOSパスに変換する。
  3. 該当パスのファイルを実行して返す

Apacheのモジュールや設定はそれぞれ段階で処理を挟みますよね。

  • mod_rewrite は リクエストを書換
  • < Location> はOSパス変換をスキップ
  • .htaccess チェックは OS パス変換
  • Allows は該当ファイルの実行時に
  • 実行はhandler に任せる。またはファイル中身を送信

今回はハンドラを追加して、バイナリを処理する

画像を自動変換する、画像の直リンク(リファラ・セッション)をチェックなど。

これらを使ってApacheのハンドラを見なおしてみる。

画像URLをPHPで処理する基本的な考え方

次の流れで、JPGファイルを送信するのではなく、間にハンドラを挟むところ。

ポイントは jpg にハンドラ(関連付け)を行う。その実行する関連付けるプログラムを自分で書こうってはなし。

Apacheのハンドラは拡張子毎に登録します。ApacheがOSと変わらん動作をするのでチャント使うと便利ってことです。

最初にハンドラを用意します。

Apache の設定側に ScriptAliasを設定。設定ディレクトリにCGI実行を許可する。

  ScriptAlias "/cgi-bin/" "/var/www/example.com/cgi-bin/"
  <Directory /var/www/example.com/cgi-bin/>
    # AllowOverride None
    Addhandler application/x-httpd-php .php
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
  </Directory>

許可したディレクトリに、独自のハンドラを追加。Apacheリロード。

$ cd /var/www/example.com/cgi-bin/
$ echo "<?php phpinfo();" > info.php

念のため、単体でphpが実行できることを確認

curl -v http://example.com/cgi-bin/info.php | grep _SERVER["SCRIPT_FILENAME"]
/var/www/example.com/cgi-bin/info.php

これで準備終わり。はい簡単です。

拡張子JPGを、作成した info.php で処理移譲するハンドラ設定をします。

Action my_sample /cgi-bin/info.php
AddHandler my_sample .jpg

Actionで my_sample という名前で/cgi-bin/info.php を登録する 拡張子JPGを処理するのを my_sample ハンドラに設定する。

この設定を好きな場所(htaccess / directory / conf ) に記述すればオッケ。

今回は.htaccessで /var/www/example.com/img/.htaccess に書いた。

完成したら、jpg にアクセスしてみる

curl -v http://example.com/img/sample.jpg | grep _SERVER["SCRIPT_FILENAME"]

出来た。これで指定の拡張子を任意のプログラムでApache実行できることがわかるね。

リクエストが来たファイル名はPATH_INFOでわかるね。

自分でプログラムを書いてそれで処理できる。それがCGI

CGIの仕組みは、自分でプログラムを書いて、そのプログラムを指定拡張子に関連付け、またはディレクトリを関連付けが本来の姿だった。

そのプログラムをphp / ruby / clang で記述すればいいわけですよね。

画像処理するCGIの例

画像やバイナリを関連付けで、処理するのにはいくつか便利な方法がある

  • 画像のリサイズ
  • 画像のリファラチェック
  • 画像の直リンク時にHTMLを表示する

一番大きいのは GET引数が使えること

http://example.com/img/sample.jpg?width=100

次に大きいのはリクエスト引数の文字列を使わなくてイイ

Apache側でファイルの存在確認と実行確認、パーミッションチェックまでヤってくれる。

http://example.com/show_img.php?path=sample.jpg&width=100

このような、ファイルの処理にまつわる処理を安全にできる。

パス変換やファイル存在チェックまではapahce側に依存できる。自分でプログラム書いたりフレームワークに頼らなくていい。ディレクトリ・トラバーサル脆弱性などに対応できうる。

php'er フレームワーク使いすぎ問題。CGIでいい。

ファイル処理くらい1枚のCGIで終わるものを、フレームワークかいてテストって意味なくね?

アップロード・ファイル処理する系はCGIが強いです。

js/cssPHP処理するときはコレ

拡張子 CSSもJavaScriptもPHPで処理しちゃう話 - それマグで!

js / cssPHPで処理しちゃうと楽しいよ。