Hatena::ブログ(Diary)

Yet Another Hackadelic

2009-02-05

Catalyst + FastCGI + Apache (mod_fastcgi) の設定

すっごい久しぶりにやった件。

FastCgiExternalServer /home/zigorou/myapp/MyApp/script/myapp_fastcgi.pl -socket /tmp/myapp.socket

<VirtualHost *:80>
    ServerName myapp.local
    DocumentRoot /home/zigorou/myapp/MyApp/root

    Alias /static /home/zigorou/myapp/MyApp/root/static
    AliasMatch ^/([^./]+\.[^./]+)$ /home/zigorou/myapp/MyApp/root/$1
    ScriptAlias / /home/zigorou/myapp/MyApp/script/myapp_fastcgi.pl

    ErrorLog /var/log/httpd/myapp-error_log
    CustomLog /var/log/httpd/myapp-access_log common
</VirtualHost>

mod_rewrite はあんまり自信が無い><

そういえば昔、id:nipotan さんに mod_rewrite の RewriteCond の影響範囲がホゲホゲ〜って言われたけど完全に忘れました。もうだめぽ。

2007-08-14 数学が出来ないガール

ブラウザキャッシュの挙動を見てみる

改めて勉強したかったので、こんなテストしてみました。

Apacheの設定とテスト内容

<VirtualHost *:80>
    ServerAdmin zigorou@localhost
    DocumentRoot /home/zigorou/www/cache
    ServerName cachetest.art-code.org

    ExpiresDefault "access plus 5 minutes"

    Alias /test1 /home/zigorou/www/cache/test
    Alias /test2 /home/zigorou/www/cache/test
    Alias /test3 /home/zigorou/www/cache/test

    <Location /test1>
        FileETag None
        ExpiresActive Off
    </Location>

    <Location /test2>
        FileETag Size
        ExpiresActive Off
    </Location>

    <Location /test3>
        FileETag Size
        ExpiresActive On
    </Location>
</VirtualHost>

どういう設定かまとめると、

test noFileETagExpiresActive
1 None Off
2 Size Off
3 Size On

ってなってて、それぞれのパスに対してIf-Modified-Since, If-None-Match, Cache-Controlヘッダを飛ばしながら200 or 304なのかどうか調べてみる。

テストスクリプト

最近のエントリはこれに繋がってた次第ですがw

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dump qw(dump);
use DateTime;
use DateTime::Format::HTTP;
use HTTP::Request;
use LWP::UserAgent;
use Set::CrossProduct;
use Text::SimpleTable;

my $date = DateTime::Format::HTTP->format_datetime(DateTime->now - DateTime::Duration->new(minutes => 30));
my $entries = {
    'Cache-Control' => [q|no-cache|, q|max-age=0|, undef],
    'If-None-Match' => [q|"2232"|, q|"2222"|, undef],
    'If-Modified-Since' => [$date, undef]
};

sub request {
    my ($url, $headers) = @_;

    my $ua = LWP::UserAgent->new;
    my $req = HTTP::Request->new('GET', $url);

    for (keys %$headers) {
        $req->header($_, $headers->{$_}) if ($headers->{$_});
    }

    my $res = $ua->request($req);

    return ($req, $res);
}

my $cp = Set::CrossProduct->new([values %$entries]);
my @headers = ();

for my $header_vals ($cp->combinations) {
    my %header;

    @header{keys %$entries} = @$header_vals;
    push(@headers, \%header);
}

for my $idx (1..3) {
    my $table = Text::SimpleTable->new([6, "no"], [20, "Cache-Control"], [20, "If-None-Match"], [20, "If-Modified-Since"], [7, "status"]);
    my $url = sprintf("http://cachetest.art-code.org/test%d/logo.gif", $idx);
    my $hidx = 0;
    for my $header (@headers) {
        my ($req, $res) = request($url, $header);

        $table->row(++$hidx, values %$header, $res->code);
    }

    print "test$idx results: \n";
    print $table->draw;
}

ちなみに正しいETagは2232です。

あと、実験でアクセスしてるファイルのstatは、

$ stat test/logo.gif 
  File: `test/logo.gif'
  Size: 8754            Blocks: 12         IO Block: 1024
・evice: 3cb4a463h/1018471523d  Inode: 844424930313348  Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1006/zigorou)   Gid: (  513/    zigorou)
Access: 2007-08-13 20:14:28.437500000 +0900
Modify: 2007-08-13 20:14:28.437500000 +0900
Change: 2007-08-13 20:14:28.437500000 +0900

で昨日がLast-Modifiedになってます。

実験結果

FileETag: None, ExpiresActive Offの場合

まずは結果。

test1 results: 
.--------+----------------------+----------------------+----------------------+---------.
| no     | Cache-Control        | If-None-Match        | If-Modified-Since    | status  |
+--------+----------------------+----------------------+----------------------+---------+
| 1      | no-cache             | "2232"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 2      | no-cache             | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 3      | no-cache             |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 4      | no-cache             | "2232"               |                      | 200     |
| 5      | no-cache             | "2222"               |                      | 200     |
| 6      | no-cache             |                      |                      | 200     |
| 7      | max-age=0            | "2232"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 8      | max-age=0            | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 9      | max-age=0            |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 10     | max-age=0            | "2232"               |                      | 200     |
| 11     | max-age=0            | "2222"               |                      | 200     |
| 12     | max-age=0            |                      |                      | 200     |
| 13     |                      | "2232"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 14     |                      | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 15     |                      |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 16     |                      | "2232"               |                      | 200     |
| 17     |                      | "2222"               |                      | 200     |
| 18     |                      |                      |                      | 200     |
'--------+----------------------+----------------------+----------------------+---------'

ここから分かるのはIf-None-Matchヘッダを送ると、有無を言わさずキャッシュが無効になり、新しいコンテンツをWebサーバーが返すって事。

Cache-Controlのno-cache, max-age=0とかは全然無関係。

なのでこの状態で有効なヘッダはIf-Modified-Since, If-None-Matchで、If-None-Matchはキャッシュ無効に無条件になり、無かったときにLast-ModifiedとIf-Modified-Sinceの比較が行われて、Last-Modified以降の日時をIf-Modified-Sinceで送っておけば304が返って来る。

FileETag: Size, ExpiresActive Offの場合

結果はこちら。

test2 results: 
.--------+----------------------+----------------------+----------------------+---------.
| no     | Cache-Control        | If-None-Match        | If-Modified-Since    | status  |
+--------+----------------------+----------------------+----------------------+---------+
| 1      | no-cache             | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 2      | no-cache             | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 3      | no-cache             |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 4      | no-cache             | "2232"               |                      | 304     |
| 5      | no-cache             | "2222"               |                      | 200     |
| 6      | no-cache             |                      |                      | 200     |
| 7      | max-age=0            | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 8      | max-age=0            | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 9      | max-age=0            |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 10     | max-age=0            | "2232"               |                      | 304     |
| 11     | max-age=0            | "2222"               |                      | 200     |
| 12     | max-age=0            |                      |                      | 200     |
| 13     |                      | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 14     |                      | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 15     |                      |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 16     |                      | "2232"               |                      | 304     |
| 17     |                      | "2222"               |                      | 200     |
| 18     |                      |                      |                      | 200     |
'--------+----------------------+----------------------+----------------------+---------'

正しいETagを送ってれば、304が返って来る。逆にETagが誤っていると無条件に新しいコンテンツを取らなくてはならない。

あとはtest1と同等。

やはりCache-Controlは無関係っぽぃ。

FileETag: Size, ExpiresActive Onの場合

結果はtest2と同じ。

test3 results: 
.--------+----------------------+----------------------+----------------------+---------.
| no     | Cache-Control        | If-None-Match        | If-Modified-Since    | status  |
+--------+----------------------+----------------------+----------------------+---------+
| 1      | no-cache             | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 2      | no-cache             | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 3      | no-cache             |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 4      | no-cache             | "2232"               |                      | 304     |
| 5      | no-cache             | "2222"               |                      | 200     |
| 6      | no-cache             |                      |                      | 200     |
| 7      | max-age=0            | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 8      | max-age=0            | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 9      | max-age=0            |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 10     | max-age=0            | "2232"               |                      | 304     |
| 11     | max-age=0            | "2222"               |                      | 200     |
| 12     | max-age=0            |                      |                      | 200     |
| 13     |                      | "2232"               | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 14     |                      | "2222"               | Tue, 14 Aug 2007 07- | 200     |
|        |                      |                      | :59:19 GMT           |         |
| 15     |                      |                      | Tue, 14 Aug 2007 07- | 304     |
|        |                      |                      | :59:19 GMT           |         |
| 16     |                      | "2232"               |                      | 304     |
| 17     |                      | "2222"               |                      | 200     |
| 18     |                      |                      |                      | 200     |
'--------+----------------------+----------------------+----------------------+---------'

何が違うかと言えば、

Cache-Control: max-age=300
Expires: Tue, 14 Aug 2007 08:43:02 GMT

のようにCache-Control, Expiresヘッダをレスポンスヘッダで返すって事。

これをブラウザが受け取り通常、期限が切れて居ない場合はリクエスト自体飛ばさない事になる。


あと、奥さんのエントリも同様に見ると勉強になります。

Kazuho@Cybozu Labs: キャッシュの上手な使い方

2007-08-13 うぅ

If-None-Matchに「*」をつけたときの挙動

http://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/http/http_protocol.c の 334行目付近参照。

    if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
    if (if_nonematch != NULL) {
        if (r->method_number == M_GET) {
            if (if_nonematch[0] == '*') {
                not_modified = 1;
            }
            else if (etag != NULL) {
                if (apr_table_get(r->headers_in, "Range")) {
                    not_modified = etag[0] != 'W'
                                   && ap_find_list_item(r->pool,
                                                        if_nonematch, etag);
                }
                else {
                    not_modified = ap_find_list_item(r->pool,
                                                     if_nonematch, etag);
                }
            }
        }
  1. If-None-Matchがセットされていて
  2. GETメソッドで
  3. if_nonematch[0]が「*」だったら

なんとNot Modifiedと言う判別になるみたい。(via ETag とキャッシュの関係(リベンジ→未解決), ETag とステータスコード 200 or 304 - まちゅダイアリー(2007-01-07))

試してみましょう。

$ lwp-request -m GET -H 'If-None-Match: *' -U -s -e -d http://localhost/test2/logo.gif 
GET http://localhost/test2/logo.gif
If-None-Match: *
User-Agent: lwp-request/2.07

304 Not Modified
Connection: close
Date: Mon, 13 Aug 2007 10:15:56 GMT
ETag: "2232"
Server: Apache/2.2.4 (Unix)
Client-Date: Mon, 13 Aug 2007 10:15:56 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1

ほんとだ。

蛇足だけどHEADリクエストにしても同じ結果になります。

2006-12-08 先ほど

X-Sendfile, X-REPROXY-FILE, X-REPROXY-URL

d:id:spiritloose:20061025:1161770915

ApacheでもlighttpdのX-Sendfileが使えるみたい。

ここで言及されてるX-REPROXY-FILEなんだけど、Perlbalの機能です。

付属のdocにあるreproxying.txtによると、

This can be useful for having URLs that get mapped to files on disk without

giving users enough information to map out your directory structure. For

example, you can create a file structure such as:

/home/pics/$userid/$pic

Then you can have URLs such as:

http://foo.com/mysite/users/$userid/picture/$pic

When this URL gets passed to the backend web node, it could return a simple

response that includes this header:

X-REPROXY-FILE: /home/pics/$userid/$pic

Perlbal will then use asynchronous IO to send the file to the user without

slowing down Perlbal at all.

とあるので、ちとlighttpdのX-Sendfileを勘違いしてる鴨ですが、

単純にPerlbalがアクセス可能なファイルシステムに対するPATHを記述すると

Perlbalが代理でファイルの内容を取得して返すってだけじゃないのかなぁ。。。

だから僕の理解*1だとX-Sendfile = X-REPROXY-FILE なんだけどどうすかね。

MogileFSとの組み合わせだと最強だと思われるのが、X-REPROXY-URLですかね。

This support also extens to URLs that can be located anywhere Perlbal has

access to. It's the same syntax, nearly:

X-REPROXY-URL: http://foo.com:80/resource.html

You can also specify multiple URLs:

X-REPROXY-URL: http://foo.com:80/resource.html http://baz.com:8080/res.htm

Just specify any number of space separated URLs. Perlbal will request them

one by one until one returns a response code of 200. At that point Perlbal

will proxy the response back to the user just like normal.

って訳でバックエンドのストレージノードのURLを列挙してあげれば、

代わりに取りに行ってくれるって理解で合ってるはず。


ちとそのうち試して追って報告するです。(誰?

*1:まだ未検証だけどもw

2006-10-30 代償とツケ

送信されるPOSTデータを制限する

LimitRequestBody ディレクティブ


これで制限出来るみたい。

Coreモジュールなのに知らなかったなんてダメな子ですね。。。

使い方

説明
クライアントから送られるHTTPリクエストのボディの総量を制限する
構文
LimitRequestBody bytes
デフォルト
LimitRequestBody 0
コンテキスト
サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccess
上書き
All
ステータス
Core
モジュール
core

だから制限するファイルサイズを適当に計算して同時にUpするファイル数とかを算出した上で、

気持ち上乗せ位の設定にしとけばOKかなーと。


ただContent-typeがmultipartな時じゃないと変なのまで引っ掛ける可能性もありますね。

Limitだけじゃ判別出来ないしなぁ。意外とApacheってプログラマブルに操作するにはディレクティブが足りない気がする。


例えばWebアプリに実際requestデータが渡された後では後の祭りみたいな事も当然ありますし、

ある程度httpd側で弾いてしまうのは有効だなーと。