アプリ版:「スタンプのみでお礼する」機能のリリースについて

Gecko エンジンでの Location ヘッダについて
http://oshiete1.goo.ne.jp/qa4227374.html

の続きです。
なんだかよく分からない状況になったのでより実際の処理とほぼ同様の
処理を行っているサンプルを用意しました。

# セッション管理
use strict;
use CGI::Session;

&main();

# メイン
sub main {
my $cgi = &getreq();
print "Pragma: no-cache\n";
print "Cache-Control: no-cache\n";
# セッション取得
my $session = &session($cgi);
# セッションが取得できない場合、再取得
if($session == undef) {
#print "Content-type: text/plain\n\n";
#print "CGISESSID=$cgi->{'CGISESSID'}\n";
$session = &session({});
# セッション ID を取得してリダイレクト
my $id = $session->id();
print "Location: ./?CGISESSID=$id\n\n";
exit;
}
my $id = $session->id();
if($cgi->{'CGISESSID'} eq '' || $cgi->{'CGISESSID'} ne $id) {
#print "Content-type: text/plain\n\n";
#print "CGISESSID=$cgi->{'CGISESSID'}\n";
# セッション ID が指定されていないまたは
# セッション ID が異なる場合リダイレクト
print "Location: ./?CGISESSID=$id\n\n";
exit;
}

print "Content-type: text/plain\n\n";
print "CGISESSID=$id\n";
print "OK\n";
exit;
}

# CGI リクエストの取得
sub getreq {
my $cgi = {};
my $query = '';
$query = $ENV{'QUERY_STRING'};

my @args = split(/&/, $query);
foreach my $i (@args) {
my ($name, $val) = split(/=/, $i);
$val =~ tr/+/ /;
$val =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig;
$name =~ tr/+/ /;
$name =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig;
$cgi->{$name} = $val;
}
delete($cgi->{''});

return $cgi;
}

# セッション取得
sub session {
my $cgi = shift;
my $dir = { 'Directory' => 'tmp' };

CGI::Session->find(undef, sub {}, $dir);

if($cgi->{'CGISESSID'} eq '') {
my $session = new CGI::Session(undef, undef, $dir);
$session->expire("1h");
return $session;
}
my $session = CGI::Session->load(undef, $cgi->{'CGISESSID'}, $dir);
return ($session == undef || $session->id() eq '') ? undef : $session;
}

こんな感じのCGIで以下のような状況の時にページを更新すると
IE(Trident)/Opera(Presto)及びSafari for Win(WebKit)では
正常に動作するのですがFxやSeaMonkey(Gecko)ではおかしな動作を
します。

1. セッションが切れた時
2. セッションファイルを手動で削除した時

具体的にはセッションが切れたら再度新しいセッションを作成して
リダイレクトをするようにしてあるのですがGeckoでは一度セッションが
切れると更新する度に新しいセッションを作成するようになってしまい
ます。
以前の質問の回答のように Status: 303 See Other ヘッダを出力して
見たのですがやはり効果はないようです。
Cookieは使いたくないのでセッションID(sesid)をCGIリクエストで
送信しているのですがこの方法がまず問題なのでしょうか。
他にも問題のある部分がありましたらご指摘お願いします。

A 回答 (1件)

直接の回答ではありませんが、



HTTPプロトコルでの「Location:」ヘッダは、規格上は絶対URLを指定することになっています。相対では指定できません。
http://www.studyinghttp.net/rfc_ja/rfc2616#Sec14 …

実際には相対URLでもたいていの場合うまく動作するようですが、
規格外のデータを受け取った時のブラウザの挙動は当てにするべきでないと思います。
まずは絶対URLを返すようにしてみてはどうでしょうか?

この回答への補足

ありがとうございます。

> HTTPプロトコルでの「Location:」ヘッダは、規格上は絶対URLを
> 指定することになっています。相対では指定できません。
> ​http://www.studyinghttp.net/rfc_ja/rfc2616#Sec14 …

> 実際には相対URLでもたいていの場合うまく動作するようですが、
> 規格外のデータを受け取った時のブラウザの挙動は当てに
> するべきでないと思います。
> まずは絶対URLを返すようにしてみてはどうでしょうか?

知っていたのですが、とりあえず基本的なブラウザではどれでも
相対パスで動作していたので問題ないかなと思ってやっていました。
やはり、絶対パスでやった方がいいんでしょうかね。

http://www.studyinghttp.net/header

によると Content-Location の方は相対パスも受け付けるみたい
なんですけど Location はなんで絶対パスなんでしょうか。

で、ここでいう絶対パスって完全なURLなのか / から始めていいのかも
分からなくて両方とも試してみましたがやはり変わらないようです。

print "Location: $ENV{'SCRIPT_NAME'}?CGISESSID=$id\n\n";
print "Location: http://$ENV{'HTTP_HOST'}$ENV{'SCRIPT_NAME'}?CGISESSID=$id\n\n";

補足日時:2008/08/05 16:14
    • good
    • 0
この回答へのお礼

今更ですが上手く解決できないので別の方法で対応することにしました。
お返事ありがとうございました。

お礼日時:2008/09/04 21:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!