レスポンスヘッダにRefreshを出力する方法だと、?以降が消去されたURLに繋がってしまうみたい。そこで、あるポータルサイトの転送でサーバーとのやりとりを見てみると、HTMLとしてmetaタグのRefreshが出力され、それによってリダイレクトしている。なるほど、metaタグのRefreshだと?以降も有効になるのか。
昨日、ADSLが開通しました。長い道のりだった…。
僕の家では収容局との間に光ケーブルが入っていたため、収容換えの工事をしてもらった。すると、以前はダイヤルアップ接続で33.6Kbpsで接続できていたのに、工事後は31Kbpsくらいでしか接続できなくなっていた。多分、光ケーブルから銅線に切り替えたので、家からNTT収容局までの間でのノイズが増加したのかな。それより、今どき33.6Kbpsも遅すぎるけれど…。
肝腎の速度は、500〜600Kbps程度。1.5MBの回線しか空きがないとのことで、フレッツADSLの1.5MBタイプに。収容局からの距離が5kmくらいあると思うので、思っていたよりは出てるのでよかった。ただ、ADSLモデムを置く位置等によっては200Kbpsくらいに落ちたりする。ノイズの影響を受けやすいということだろうけど、こんなに違いがあるとは。さすが、ベストエフォードだなぁ。
\に続けてアカウント名を書けばいいらしい。転送アドレスとの併記も可みたい。ちらっと見かけただけなので、間違っているかもしれないけど。
forward@otherdomain.net \myname
サーバーに届いたメールをプログラムに渡すには、.forwardにプログラムへのパスをパイプを使って記述するのが簡単な方法らしい。
メールをプログラムに渡すことができれば、プログラムからメールを送るにはsendmailなどを利用すればいいので、簡易的なメーリングリストなどを作ることができる。その他にもいろいろ活用方法がありそう。
ところで、レンタルサーバーのヴァーチャルホスト機能で運用しているドメインの場合、そのドメイン宛てのメールを.forwardで操作できるのかな。メインアカウントのものはできそうな気もするけど…。
uttsu.comでディレクトリ名の後に/を付けずにアクセスした場合、www.uttsu.comドメインのURLに繋がってしまう。今回、サーバーのレスポンスヘッダを調べてみた。
すると、例えばuttsu.comの/diaryにアクセスすると、以下のようなリクエストヘッダが送られる(一部)。
GET /diary HTTP/1.0
それに対し、サーバーからは以下のようなレスポンスヘッダが返される(一部)。
HTTP/1.1 302 Found Location: http://www.uttsu.com/diary/
uttsu.com/diary へのアクセスに対し、www.uttsu.com/diary/ にアクセスするように返しているのが分かる。Locationでは完全なURLを返す必要があるので、サーバーで先に記述されているwww.uttsu.comのドメインを返してしまうみたい。
そういえば、ディレクトリ名の後ろに/がない場合の振る舞いも設定できた気がするけど、.htaccessでも可能だったかな。調べてみよう。
自分の作ったプログラムと他人のプログラムを対戦させたいときは、審判のプログラムを作って、互いのプログラムを交互に呼び出してやればいいのか。データの受け渡しは、コマンドライン引数かファイルでできるし。
審判プログラムは、勝負の終了判定と差し手のルール判定を行い、一手ごとにその局面をファイルなどに保存して、先手後手などの情報とともにプレイヤープログラムを呼び出せばいい。あと、必要なら考慮時間の管理も。
OSなどの動作環境が異なる2つのプログラムを対戦させるときは、ネットワークで繋いで対戦させることになると思う。この場合、プレイヤープログラム側でネットワークを意識せずに対戦させる方法はあるかな? もしできるなら、プレイヤープログラム側としては同じインターフェイスでよいので、様々な環境に対応できるのだけど。
同じOSで動く2つのプログラムの場合は、簡単に対戦させられそう。プレイヤーソフト側でも比較的簡単に対応できそうだし。今度オセロか何で試してみようかな。
友達とオセロで試してみることに。うまくいくかな。
<a href=?hoge>とした場合、IEでは現在のURLのパス名(?以前まで)に?hogeをつけたURLへのリンクとなる。一方、NN 4.xの場合は、現在のURLの最後の/に続けて?hogeとしたURLへのリンクとなる。例えば、page/index.htmlに<a href=?hoge>があった場合、IEではpage/index.html?hogeへのリンクと見なされ、Netscapeではpage/?hogeへのリンクと解釈されるみたい。Netscape 6ではIEと同じだった。
mod_rewriteを用いたダウンロードカウンターに欠点があることが分かった。それは、CGIによってファイルを出力しているので、.htaccessによってアクセス制限をかけているファイルでもダウンロードできるようになってしまうということ。うーん、欠点はなさそうに思ったんだけどなぁ。
これを回避する方法はいくつか思いつくけど、どれもあまりスマートではなさそう。こうなれば、ダウンロード専用ディレクトリに特化したスクリプトにするのがよさそう。サブディレクトリ以下のファイルにも有効なので、たとえば/softwareでmod_rewriteの設定をしておけば、/software以下のすべてのダウンロードファイルに対応できる。これでも十分便利っしょ。
CGIでダウンロード用のバイナリファイルを出力するときは、サーバーから返すヘッダにContent-type: application/octet-streamとContent-Disposition: attachmentを指定するみたい。
Content-Type: application/octet-stream Content-Disposition: attachment
で、index.cgiからhoge.lzhのファイル内容を出力したときは、ダウンロードしたファイル名はindex.cgiになる。mod_rewriteを利用してhoge.lzhというURLをindex.cgiというスクリプトに対応させたときでも、ダウンロードしたファイル名はhoge.lzhになるのかと思いきや、なんとindex.cgiという名前で保存される。ちゃんとhoge.lzhというファイル名で保存されるようにするためには、サーバーが返すヘッダにContent-Disposition: attachment; filename=○○を追加する必要があるみたい。さらに、Content-Lengthとしてファイルサイズを出力すると、ダウンロード前にクライアント側でファイルサイズを知ることができる(もしかしてContent-Lengthの出力は、ダウンロードのレジューム機能にも関係あるのかな?)
Content-Type: application/octet-stream Content-Disposition: attachment; filename=ファイル名 Content-Length: ファイルサイズ
それから、ちゃんとヘッダの出力やbinmodeの指定をしても、サーバーやブラウザの組み合わせによってはダウンロードが開始せず、テキストファイルみたいにウィンドウにファイルの内容が表示されてしまうことがある。なんでだろ? 今日からアクセスカウンターの運用を開始して、lzhファイルはCGIで出力するようにしてみたけど、ファイルの出力がこんなに奥が深いとは知らなかった。
mod_rewriteを使ってファイルのダウンロード数をカウントするスクリプトを作ってみた。特徴は、download/hoge.lzhのような普通のURLなのにカウントできるところ。mod_rewriteを使えば、例えばディレクトリ構成が以下の場合、
download/ count.cgi hoge.lzh
(http.confでmod_rewriteの設定をしていない場合は、他に.htaccessが必要)
download/hoge.lzhへのアクセスがあった場合、download/count.cgi?hoge.lzhを実行することができる。つまり、URLは実際にあるファイルを示しているけれど、サーバーがそのファイルを返す間にCGIによる処理を挿入できるということ。
一般的なカウンターの場合、ファイルごとにIDを設定したりする必要があって、ファイルが増えてくるとその管理に結構手間がかかる。でもこの方法だとそういった設定は一切不要。また、URLにいかにもCGIで処理しています、というような?の文字が入らない。
この方法は他にも、リンク切れがないかローカルでチェックすることができるというメリットもある。また、何の設定もなしにサブディレクトリ以下にあるファイルにも対応でき、download/category/hoge.lzhというような使い方もできる。さらに、特定の拡張子にだけ反応するように設定して、ルートディレクトリにcount.cgiを置いておけば、それだけでサイト全体の特定の拡張子のすべてのファイルのダウンロード数をカウントできる。ファイルを追加する場合、何の追加設定も、ダウンロード専用のディレクトリに置く必要もない。
mod_rewriteは他にも便利な活用方法がありそうだなぁ。
先日書いたReferrer消去リダイレクトだけど、mod_rewriteを導入してURLから?をなくしてみた。下のリンクをクリックすると実験できます。
リンク元:なお、http://uttsu.com/r/は、利用可能なリンク元を限定しています。
上の実験で気付いたけど、リダイレクトの種類によっては(すべて?)URLの#以降が消去されてしまうみたい。これはサーバーかクライアントかどちら側が原因なのかな。以前にも同じようなことをどこかで読んだ覚えがあるので、やっぱりサーバー側かな。
それから、Netscape4.xでは「ドキュメントにデータが含まれていません」と表示された。必要なヘッダを出力し忘れているのかな? でも、一応リダイレクトはできた。
この間はできなかったけど、URLに/をつけてCGIにアクセスする方法が使えるようになった。この日記のURLは以前と同じだけど、yyyymmdd.htmlというURLへのアクセスに対して実はその都度CGIで内容を出力している。こうすることによって、各日の日記へのリンク元を日記のCGIで収集したりできるし、HTMLファイルを置かなくていいのでファイル数を少なくできる。
あるURLへのアクセスを別のURLへ渡すにはmod_rewriteというものを使うらしい。今回の設定内容は以下。.htaccessファイルに記せばOK。
RewriteEngine on RewriteBase /diary RewriteRule (.*)\.html$ index.cgi?$1
diaryディレクトリ中のファイル構成は以下。
diary/ .htaccess index.cgi style.css
多分この応用で、ファイルのダウンロード数をカウントするCGIとかもできそう。例えば、download/○○.lzhへのアクセスを受け取り、実際のファイルを出力するようにすればいい。見た目には普通のURLに見えるので便利。
気付いた点を少し。
AN HTTPDを使っている場合は、「オプション一般」の「CGI出力を検査」をチェックしておくと、CGIがエラーを起こしたときにブラウザ上に表示してくれる。
uttsu.comへのアクセスで、URLがディレクトリ名で終わっているときに最後に/をつけないと自動的にwww.uttsu.comのドメインへ接続される。uttsu.comとwww.uttsu.comは内容は同じなので問題はないのだけど、できたらuttsu.comに統一したいな。
このことについて調べてみたら、サーバーの設定で、www.uttsu.comがuttsu.comよりも前に記述されていることが分かった。多分、/がない場合は再度サーバーへ問い合わせになるけど、そのときにwww.uttsu.comを参照するようになっているのではないかな。
これを.htaccess等を使ってユーザー側で設定したり、www.uttsu.comかuttsu.comかどちらへのアクセスかを判断することができれば対処もできるのだけど、その方法ってないかな。
CGIにパスワード認証機能をつけるとき、どうすれば一番パスワードが漏れにくくなるかな。
REQUEST_METHODをGETにするとパスワードがURLに含まれてしまうので、ブラウザのアドレス欄に表示されてしまう。
同じくPOSTにするとその問題は回避できるんだけど、一度だけパスワードを入力して、そのパスワードを引き継いで他のページに移動したい場合、一度目に出力したHTMLコードの中に<input>タグなどと一緒にパスワードを出力しておく必要がある。GETの場合と違って画面には出ないのでまだいいけど、キャッシュされたHTMLファイルを見ると分かってしまうので、共用のパソコンを使う場合は全く問題がないわけではないし。クッキーを使う方法もあるけど、なるべく使わないでも動作するものを作りたいし。
他に、認証が必要なCGIを別のファイルにして、BASIC認証をかけるという方法もある。でも、ファイルが分かれてしまうのと、BASIC認証に対応していないブラウザ(J-Phoneのものなど)だと使えない欠点がある。
チャットなどでCGIが会話の相手(?)をしてくれるものがあるけど、アイデアはなかなか面白いなぁ。
チャット以外でも、CGIを使って自動的に学習していくシステムを作れるんじゃないかな。たとえば、対戦型のボードゲームとか。この場合、すべてCGIで処理していては動作が遅くなるので、Javaなどと連携させるとよさそう。一度はこういうプログラムも書いてみたいな。
ブラウザ上から簡単にページ自体を書き換えられるのは便利そう。これだと簡単にページを更新できるし、何よりも、HTMLを知らない人でもホームページが作れる。YukiWikiを参考にスクリプトを書いてみたけど、シンプルなものなら結構簡単に作れる。YukiWikiMiniはシンプルなスクリプトなので勉強用におすすめ。
やっぱ日記のページを自動出力すると便利だなぁ。あと追加したい機能としては、引用(<blockquote>に相当)と画像表示、それから携帯から見るときのCGI。でも長文の日記だとパケット料が…。
Perlにもだいぶ慣れてきたので、テキストファイルを読み込んで日記ページを作成するスクリプトを作ってみた。スクリプトの概要は以下のとおり。
コンセプト:
主な機能:
例えば、ここまでの日記は次のように簡単なものになっている。
日記システム Perlにもだいぶ慣れてきたので、テキストファイルを読み込んで 日記ページを作成するスクリプトを作ってみた。 スクリプトの概要は以下のとおり。 コンセプト: ・Simpleな設計、データ形式にする ・データファイル自体が普通に日記として読めること 主な機能: ・セクションごとにアンカーを出力 ・最新、月毎、日毎のページを出力する ・URL自動リンク機能 ・・で始まっている行は、自動的に<ul><li>…</ul>に変換 ・<pre>〜</pre>はそのまま出力 ・&, <, >などはエスケープ文字に置き換える etc…
本当は、diary/20020813.htmlのようなHTMLファイルのURLでアクセスしてもCGIでそのファイルを出力する仕組みにしたかったんだけど、それにはdiary/○○.htmlへのアクセスをCGIへ渡す必要があり、その設定が面倒そうなので断念。
HTMLファイルへのURLをCGIの引数として受け取る方法にはもう一つあって、上の例だと、diaryという名前のスクリプトを用意すればいい。こうすると、diary/20020813.htmlというアクセスがあった場合、そのファイルが存在しないので、diary(というCGI)が実行されることになる。CGI側でURLを受け取るには環境変数PATH_INFOを参照すればいい。
他に考えたのは、URLの?のあとに日付けを付けて読みたい日を指定する方法。URLは例えば/diary/?20020813のようになる。この方法は簡単に実装できるけど、検索エンジンによっては?の付いたURLだと拾ってくれないものがある。ということで今回は予めHTMLに変換しておく方法を採用。URLに?をつけるバージョンも作ってあるので、もう少しまとまったら公開しようかな。
2ちゃんねるやポータルサイトのウェブメールサービスなどで、リンク元のURLであるRefererを渡さずにリダイレクトするCGIが使われているけど、それにはLocation:でなくRefresh:を使っているみたい。実はRefreshの場合もRefererを渡すか渡さないかはブラウザ次第なのだけど、ちょうどExplorerとNetscapeで渡さないようになっているので、大半の利用者に対応できるらしい。スクリプトの例は以下。アクセスは、redirect.cgi?URLのようにすればOK。
my $url = $ARGV[0]; print "Refresh: 0; URL=$url\n\n";