CGIでHTTPヘッダー「Content-Length」を出力するには?

[上に] [前に] [次に]
ma3ki 2000/02/21(月) 16:44:39
CGI(Perl)において、HTTPヘッダー「Content−Length」
を出力するには、どのように書けば良いのか?
また、Lengthとは何の長さなのか?
まったく分かりません。
いろいろ調べましたが、「Content−Type」については書いてありますが?
お分かりになりましたら教えて下さい。
よろしくお願いします。

B-Cus 2000/02/22(火) 02:59:35
$data="Hello, world.\n";

print "Content-type: text/plain\n";
print "Content-length: ",length($data),"\n";
print "\n";
print $data;

びぎな++ 2000/02/22(火) 09:52:24
横からすいません。

Content-lengthの出力はどういった意味,メリットがあるんですか?
また,どんなときに出さなければいけないのでしょうか?

無責任官庁 2000/02/22(火) 10:14:41
>どんなときに出さなければいけないのでしょうか?

私の知ってる所だと、iモード用サイトは出力必須のようです。

http://www.nttdocomo.co.jp/mc-user/i/tag/s3.html#3_4

B-Cus 2000/02/22(火) 17:36:44
> メリットがあるんですか?
ブラウザによっては「あと〜秒」「〜% 読み込み済」などと表示され、
読み込みの際のユーザの体感時間を減らすことができます。

CGI の仕組み上、ヘッダ出力時に全体の長さをはかることは
難しい場合もありますが、できる限り出力した方がよいです。

wosamu 2000/02/22(火) 19:14:43
びぎな++さんに続いて横からすいませんけど
このContent-lengthってWebブラウザで見て出力されたやつの
プロパティで表示されるサイズでよいのでしょうか?
それなら簡単そうだけど。(固定値なら)
これって間違った値を指定した場合って
なんか不具合あります?

ma3ki 2000/02/22(火) 19:31:48
B-Cus さん、早速のレス有り難うございます。
サンプルに従い試みましたが、
HTML上に表示されてしまします。
これが良いのか悪いのか分かりませんが
とりあえず、報告します。

■CGI(仮に1000バイトとしました)

sub html {

   print "Content-type: text/html\n\n";
   print "Content-Length: ",1000,"\n";
   print "<html><head><title>schedule</title></head>\n";
   print "<BODY>\n";
   print "<b>$FORM{'namae'}さんのスケジュール</b>\n";
                 ・
                 ・
■結果(ブラウザ。iモード携帯ではありません。)

Content-Length: 1000 末広さんのスケジュール
-----------------------------------------------
SetDate=20000222
EndDate=20000222
Event=休
Detail=
Place=
Other=
Memo=

--------------------------------------------------
1件見つかりました。

末広 2000/02/22(火) 20:27:05
>   print "Content-type: text/html\n\n";
>   print "Content-Length: ",1000,"\n";

\n\nではヘッダが終了してしまいます

   print "Content-type: text/html\n";
   print "Content-Length: ",1000,"\n\n";

あと,は.のような気がしますが…

ma3ki 2000/02/22(火) 21:03:36
末広さん有り難うございます。
成功しました。
ほんとは、広末とたたいたつもりですが?
ついでで申し訳ありませんが、
Charsetを指定する場合は、どのよううに
書けば良いかご存知ですか?

びぎな++ 2000/02/22(火) 21:34:41
print "Content-Type:text/html; charset=Shift_JIS\n";
print "Content-Length: ",1000,"\n";
print "\n";

じゃないですか?
僕はヘッダの終了を表す改行は一行設けてしてます。
その方がわかりやすいかな?と。 初心者なんで。(^^;

びぎな++ 2000/02/22(火) 21:49:59
無責任官庁さん,B-Cusさんありがとうございました。
#お礼を言うのを忘れていました。 すいません。m(_ _)m

>print "Content-Length: ",1000,"\n";
print "Content-Length:1000\n";
ではだめなんですか?(もし,直接数値を入れるなら)

B-Cus 2000/02/22(火) 23:30:53
> これって間違った値を指定した場合ってなんか不具合あります?
NN4.7 では、ボディの長さより短い値 (=間違った値) を
Content-length に指定すると、指定した値しか読んでくれません
でした (最後の部分を読んでくれなかった)。

なので、よく理解してないなら Content-length を出力するのは
やめましょう。読めなくなるよりマシです。


あと、
 $data = "<HTML>\n";
 $data. = "<BODY>\n";
 $data. = ".....";
 ...
 print "Content-type: text/html\n";
 print "Content-length: ",length($data),"\n";
 print "\n";
などとするくらいなら、Content-length を出力しないほうが
マシかもしれません。

全体の長さが確定しないとヘッダが送られないわけで、
結果的にユーザへのレスポンスが遅くなる可能性がありますし、
メモリも無駄です。


もう一度言いますけど、よく理解してないなら Content-length を
出力するのはやめておいた方がよいでしょう。

末広 2000/02/23(水) 09:17:20
>>print "Content-Length: ",1000,"\n";
>print "Content-Length:1000\n";
>ではだめなんですか?(もし,直接数値を入れるなら)
いいと思うんですけど、HTMLのサイズは固定なんですか?

>もう一度言いますけど、よく理解してないなら Content-length を
>出力するのはやめておいた方がよいでしょう。

3.4. HTTPヘッダ
   CGI作成時に「Content-Type」、「Content-Length」は必須項目となります。

iModeはパケット課金なので多少遅くても構わないと思います(氏感)
むしろ必須項目と言われている以上 出すべきだと思います
仮に出さないで 今の端末では動いたとしても 今後発売される端末で動くとは限らないのでは?
あと、端末のバッファも小さいので(5〜10KByte)あまり大きなデータは
(一度には)送れないはずなので、メモリの無駄も少ないはずです。

# Content-Lengthをチェックすれば端末側の制約(バッファサイズ)を
# チェック(した上で回避)できるかもしれない…

末広 2000/02/23(水) 11:21:41
う゛っ
すみませんiModeじゃないんですね、
ゴメンナサイ m(__)m

必須でないならContent-length は出さなくもいいと思います、

ma3ki 2000/02/23(水) 11:43:23
[[解決]]
皆さん、有り難うございました。
まだ、実機(iモード携帯)での確認が出来ていませんが
まづはブラウザでの確認が取れたので、解決とさせて頂きます。
Lengthについては、CGIアプリのロジックの関係から、
ヘッダー出力時には、出力データ量が分からないので、
1500固定とします。
前々回の投稿の結果が、1件あたりのデータ量です。
1日1人あたり5件あるとして、1行平均20バイトとして
11行ゆえ1100バイト。余裕をみて1500とします。

このCGIは、外から社内のスケジュールをiモード携帯で
確認するために作成しました。
元になるスケジュールのデータは、サイボウズのスケジュールファイル
です。

B-Cusさん、wosamuさん、びぎな++さん、無責任官庁さん、
末広さん有り難うございました。
また、実機での確認のトラブルで投稿した折りには
よろしくお願いします。

ねえ 2000/02/23(水) 13:36:44
解決ついてるのにナンですが、
レングスを計算するのは B-Cus さんのやりかたで
一度バッファに入れて length() を取ればいいだけだとおもいます。
間違った値を出力するのは ちょっと。

masa3ki 2000/02/23(水) 15:08:48
ねえさんへ、
大変失礼しました。
ねえさんのお怒りはごもっともですが、
大きさの問題に付いては、iモードにつてドコモ様が提示している
仕様は
「HTMLの大きさは、2KB以内を推奨し5KB未満とする。」
となっています。
今回作成したCGIは、1.5KBと推定していますが仮に倍になっても
3KBで問題ありません(gifファイルなし)。
CGIのロジックの関係上、HTTPヘッダーを出力する時点で、大きさが
不明なため、最大値を採用することにしました。

どうぞ、ご理解のほどお願い申し上げます。

ねえ 2000/02/23(水) 15:59:53
いえいえ 怒ってないです(笑)
わたしが心配しているのは、

レングスに正しくない(大きい)値を設定することによって
データを全て受けとっているのに端末はまだデータが有ると
認識して動作がおかしくならないか?
又 データ量課金なので 余計な課金がされないか?

と思ったのですが、余計なおせっかいでしたら無視してください、
それでは失礼します。

Syn [E-Mail] 2000/02/23(水) 16:04:56
> 今回作成したCGIは、1.5KBと推定していますが仮に倍になっても
> 3KBで問題ありません(gifファイルなし)。

いや、そーゆー問題ではなく、 Content-Length: フィールドが示す
情報の意味として、適当な数字を入れるという行為自体が根本的に間違っ
ているのではないか、とゆー指摘だと思うのですが。

ロジック的に問題があるというのは、 print "〜" を $buffer .= "~"
に置き換えるとスクリプトが動かなくなるとか、クリティカルな問題
なんでしょうか。

> 3KBで問題ありません(gifファイルなし)。

「問題ありません」の持っていきようとしては「3KB ぐらいまでなら
バッファにためて length() しても問題ありません」のほうがイイのでは
ないでしょうか。

というか、いつのまにか i-mode が要件に含まれているのですね(^_^;

ma3ki 2000/02/23(水) 18:23:49
Synさん、はじめまして。
私が、ここラウンジを利用して知りたかったことは、
書式についてです。
Lengthの問題は、アプリのテクニック上の
問題と考えます。
3k位は、確かにバッファーにため込めば良いのですが
私の技量がそのうにさせてくれません。
最初iモードを出さなかったのは、書式について知りたかったためです。

どうぞ、ご容赦ねがいます。

B-Cus 2000/02/23(水) 18:48:04
> Lengthの問題は、アプリのテクニック上の問題と考えます。
明らかに違います。もし HTTP/1.1 だったら致命的かも
(試してないけど)。

あなたの環境で問題ないなら別に構いませんが、Content-length を
使うならちゃんと計算して正しい値を出力すべし、ということは
はっきりと書いておきます。

末広 2000/02/23(水) 19:03:07
やっぱりiModeだったんですね ^^;
もし正確な Content-length を出力したくなったら、

B-CusさんのPG
> $data = "<HTML>\n";
> $data. = "<BODY>\n";
> $data. = ".....";
> ...
> print "Content-type: text/html\n";
> print "Content-length: ",length($data),"\n";
> print "\n";
> print $data;  #この行はオリジナルには無かったね

を参考にしてください 一度全HTMLを $DATAに格納して
ヘッダを出力した後に全文を出力する仕組みです、簡単です ^^;

>Lengthの問題は、アプリのテクニック上の
>問題と考えます。
この見解が正しいとは思えませんが、
どうするかはご本人の自由なので
これ以上続けても仕方が無いですね。

実機での動作確認頑張ってください > ma3kiさん

ma3ki 2000/02/23(水) 20:51:11
B-Cusさん、末広さん、Syeさん、ねえさんへ

私の見解が誤りであることを痛感しております。
皆様のご意見に従い、次のようにさせて頂きました。

ブラウザ(IE4)で確認したところ、数行データが欠落しますので
+50してあります。
ヘッダー部分が足らないのか?


sub htmlout {

       print "Content-type: text/html; charset=Shift_JIS\n";
       print "Content-Length: ",length($data)+50,"\n\n";
       print $data;
}

いろいろご迷惑をおかけしました。
応答の仕方、解決のタイミングよい勉強になりした。
(自分では、こう言う性格であることは分かっています)
では、失礼します。

B-Cus 2000/02/23(水) 21:17:03
Windows 環境で、出力する HTML が50行程度ならば、改行コードでしょう。
試してないけど length($data) + $data=~s/\n/\n/g とするか、
binmode(STDOUT) かな。

> ヘッダー部分が足らないのか?
ヘッダ部分を数える必要はありません。

ma3ki 2000/02/25(金) 13:15:28
B-Cusさん、他の作業が入り報告が遅れました。

次のように書き、特に異常は無いようです。
(NT IIS、UNIX,AN HTTPDの何れの環境も
IE使用の下で異常無ありません)

sub htmlout {
       print "Content-type: text/html; charset=Shift_JIS\n";
       print "Content-Length: ",length($data)+$data=~s/\n/\n/g ,"\n\n";
       print $data;

}

ただ、次のことがよく理解できないのですが教えて下さい。
+$data=~s/\n/\n/gは、長さとして評価されているのですか?

実機(携帯)での確認は、今日明日中に予定しています。
他のところ(TOPページ)で心配が1件あります。そこで
wwwcountを使用していますが、Content−Type text/html
で上手く以下かが気がかりです。
その結果は、追って報告します。
では、失礼します。

安藤 2000/02/25(金) 15:34:32
>$data=~s/\n/\n/g
$data の中の\nを\nで置き換えた回数

ラウォッチ 2000/02/25(金) 15:40:16
横から失礼!

>+$data=~s/\n/\n/gは、長さとして評価されているのですか?

=~ 演算子 で s/// の時は置換数を返します。

(パール勉強したところなので、ちょっと云いたかっただけ...)

ラウォッチ 2000/02/25(金) 15:43:04
ありゃ〜、遅かった!

安藤 2000/02/25(金) 16:37:30
>=~ 演算子 で s/// の時は置換数を返します。
この場合 =~ は問題じゃないので、($_なら書かなくてもいいわけだし)
値を返してるのs///なので、

s/// 演算子 は置換数を返します、その際対象の指定は =~ でします。
かな?

ラウォッチ 2000/02/25(金) 18:03:20
ご指摘ありがとうございました。
今、パール勉強中なので、またいろいろ教えて下さい!

B-Cus 2000/02/25(金) 18:18:33
> 実機(携帯)での確認は、今日明日中に予定しています。
という確認も大事だけど、ちゃんとサイズのチェックもしてね。

Content-length を出さずに、NN や IE で見たとき
 表示->ページの情報
で表示されるサイズと、
 「length($data)+$data=~s/\n/\n/g」
で計算したサイズが一致するかどうかが重要です。

# s///g や tr/// 以外で、任意の文字 (文字列) を数える
# 簡単な方法ってありましたっけ?

ma3ki 2000/02/25(金) 18:42:41
B-Cusさん、無責任官庁さんへ
実機での確認成功しました。
wwwcountも上手く(2階調白黒gif)表示できました。

本当に、有り難うございました。
Syeさん、ねえさん、私のご無礼をお許し下さい。

B-Cus 2000/02/26(土) 03:55:33
で、
> という確認も大事だけど、ちゃんとサイズのチェックもしてね。
はどうなったのですか?

「実機で動いた。よかったよかった」では、適当に +50
してるのと変わりません。

しなのむし 2000/02/26(土) 06:40:52
>ブラウザ(IE4)で確認したところ、
>数行データが欠落しますので+50してあります。
>ヘッダー部分が足らないのか?

出力する前に
binmode(STDOUT);
と一行付け加えるだけです。

# せっかくB-Cusさんが貴重な情報をくれてるのだから
# 試すだけ試しましょうよ。

ma3ki 2000/02/27(日) 12:48:37
>表示->ページの情報
>Content-length を出さずに、NN や IE で見たとき
> 表示->ページの情報
>で表示されるサイズと、
> 「length($data)+$data=~s/\n/\n/g」
>で計算したサイズが一致するかどうかが重要です。

私の作成したcgiでは、IE、NNともページのプロパティ
及びファイル情報で、サイズが表示されません。
そこで、他のcgi(vote.cgi:レスキュー)で試みました。
■1.まず、無加工でIE、NNで確認したサイズは、ともに1480バイト。
■2.次に、vote.cgiの全ての「print」行を次のように修正しvote1.cgiで保存。
print "<html><head><title>$title</title></head>\n";
$data = "<html><head><title>$title</title></head>\n";
vote1.cgiを起動しサイズを確認したら、同じか1480バイトで
$dataを挿入しても同じサイズを確認。
■3.
次に、つぎのスクリプトを次のように挿入(vote1.cgi)。
        ・
        ・
print "</body></html>\n";
$data .= "</body></html>\n";
print "Content-Length: ",length($data),"\n";
print "Content-Length: ",length($data)+$data=~s/\n/\n/g ,"\n";

その結果は、次のように表示されました。

Content-Length: 1445 Content-Length: 1480

Content-length を出さずに、NN や IE で見たとき
 表示->ページの情報
で表示されるサイズと、
 「length($data)+$data=~s/\n/\n/g」
で計算したサイズが一致しました。
下は、■2.の時のファイル情報(IE)

場所:
                  http://127.0.0.1/E01/cgi-bin/vote1.cgi
  ファイルMIMEタイ
               プ:
                  text/html
           ソース:
                  現在、メモリキャッシュに入っています
  ローカル キャッシ
       ュ ファイル:
                  なし
    最終更新日時:
                  不明
    最終更新日時:
                  不明
       内容サイズ:
                  1480
        有効期限:
                  日付なし
        文字セット:
                  不明
      セキュリティ:
                  このドキュメントでは暗号化によるセキュリティ保護は行われていません。

ma3ki 2000/02/27(日) 15:07:17
↑前回投稿の補足
>■2.次に、vote.cgiの全ての「print」行を次のように修正し…
は、
■2.次に、vote.cgiのHTTPヘッダーprint行は除き、全ての「print」行を次のように修正し…
に訂正させてください。
HTTPヘッダーprint行は除いています。

[上に] [前に] [次に]