出力方法

ここでは、ruby の使い方というよりは、HTTP の仕様とその使い方について、解説します。

CGI では、puts や print などで標準出力に書き出された内容が、そのまま読者のブラウザへと送られます。

標準出力へ書き出す内容は、ファイル名やファイルの種類などのデータの特性を表す「ヘッダ」部分と、表示させる本体を表す「ボディ」に分かれていて、その境い目は、最初の空行で表されます。

Step1: 英文をテキストファイルとして表示してみよう

下記内容のファイルを作成し、ファイル名を test.cgi として、サーバーにアップロードし、接続してみてください。


#!/usr/local/bin/ruby
puts "Content-type: text/plain" # ヘッダ(データの情報)を出力
puts                            # 仕切りとして、空行を出力
puts "Hello world!"             # ボディ(表示させる本体)を出力
#!/usr/local/bin/ruby
print <<KEYWORD
Content-type: text/plain

Hello world!
KEYWORD

Step2: 和文をテキストファイルとして表示してみよう

test.cgi を下記の内容に書き直して、サーバーにアップロードし、接続してみてください。

#!/usr/local/bin/ruby -Ks
print <<KEYWORD
Content-type: text/plain;charset=Shift_JIS

世界のみなさん、こんにちは。
KEYWORD
文字コードオプション特徴
Shift_JIS-KsWindows標準。とっても古い文字体系。ボロいケータイ端末でも表示できる。
EUC-jp-KeUNIX系サーバーで多く採用されている。Shift_JIS より新しい。
UTF-8-Ku世界中の文字を表せる。これからの標準。なるべくこれを使いたい。

Step3: 保存時のファイル名を指定してみよう

test.cgi を下記の内容に書き直して、サーバーにアップロードし、接続してみてください。

#!/usr/local/bin/ruby -Ks
print <<KEYWORD
Content-Disposition: filename="hello.txt"
Content-type: text/plain;charset=Shift_JIS

世界のみなさん、こんにちは。
KEYWORD

Step4: HTML を出力してみよう

test.cgi を下記の内容に書き直して、サーバーにアップロードし、接続してみてください。

#!/usr/local/bin/ruby -Ks
print <<KEYWORD
Content-Disposition: filename="hello.html"
Content-Type: text/html;charset=Shift_JIS

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
  <title>テストページ</title>
</head>
<body>
<p>世界のみなさん、こんにちは。</p>
</body>
</html>
KEYWORD

Step5: データ長さを明示しよう

通信が完了する前にプログラムが終了してしまうことに起因して、受信されるデータが途中で切れてしまう場合があります。 送受信双方の仕様によっては、この問題はめったに起こりませんが、送信側の設定が特殊だったり、受信側が i-mode などだったりすると、どうなるかわかりません。 予めデータの長さが明示されていれば、送信の完了が受け手側でわかるので、このような中断を未然に防ぐことができます。(たぶん)

#!/usr/local/bin/ruby -Ks
html = <<KEYWORD
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
  <title>テストページ</title>
</head>
<body>
<p>世界のみなさん、こんにちは。</p>
</body>
</html>
KEYWORD

print <<KEYWORD
Content-Disposition: filename="hello.html"
Content-Type: text/html;charset=Shift_JIS
Content-Length: #{ html.length }

KEYWORD
print html

Add-on#1: GIF 画像を表示させる

test.cgi を下記の内容に書き直して、サーバーにアップロードし、接続してみてください。
同じディレクトリ内に、ファイル名 hogahoge.gif の GIF 画像も置いてください。

#!/usr/local/bin/ruby
                                   # ↓ヘッダ部分と空行を出力
print <<KEYWORD
Content-Disposition: filename="hello.gif"
Content-type:   image/gif
Content-Length: #{ File.size("hogahoge.gif") }

KEYWORD
f = File.open("hogahoge.gif","rb") # 画像ファイルを開く
STDOUT.binmode                     # ←たいていは不要。一部のマイクロソフト社製サーバーで有効。
while line = f.gets do             # データを1行づつ読み込み変数lineに写し取る
  print line                       # 画像データを出力
end
f.close                            # 画像ファイルを閉じる

Add-on#2: 飛ばし技を使う

test.cgi を下記の内容に書き直して、サーバーにアップロードし、接続してみてください。
同じディレクトリ内に、ファイル名 hogahoge.gif の GIF 画像も置いてください。

#!/usr/local/bin/ruby
puts "Location: ./hogahoge.gif"
puts

Add-on#3: データが途中で切れてしまう場合の対策

Add-on#4: キャッシュさせたくないページ

  1. ケータイ端末などでは、通信会社のサーバーに閲覧データを一時保存して、その保存されたデータを端末で見ている場合があります。この保存されたデータを「キャッシュ」といいます。
  2. パソコンでページを見ている場合にも、ブラウザ(=閲覧ソフト)が、パソコンの中にデータを一時保存します。これも「キャッシュ」といいます。
  3. CGI では条件に応じて内容を変化させるわけですが、キャッシュを見てしまうと、本来あるべき表示が見られません。 パソコンの場合は、あまりキャッシュの問題はおこりませんが、一部のケータイでは、内容がキャッシュで固まってしまって、動かなくなります。
  4. 普段はムダな通信を節約してくれるキャッシュですが、このように邪魔になる場合があります。
  5. そこで、キャッシュを防止するためには、ヘッダに下記を書き入れます。
    Expires:       -1
    Pragma:        no-cache
    Cache-Control: no-cache
    
    …たぶん、これでいけると思いますが、使えなかったらすみません。
  6. キャッシュされないということは、ケータイでページを見にきた人の「パケ代」が高くつきます。使用は必要な部分にだけに、限定してください。

Appendix

文字/改行コード指定と、UTF-8 保存時の BOM の除去方法

HTTP レスポンスヘッダを見てみよう

ヘッダは通常は表示されませんが、必ずページの内容と一緒に送られてくるものなので、簡単に見ることができます。 いろいろなサイトや CGI のヘッダを観察して、意味を調べてみてください。

方法1 - Firefox に、機能拡張 WebDeviloper を入れて使う

方法2 - curl でサイトに接続してみる

コマンドラインから、下記のように入力してみる

curl -I http://www.google.co.jp

方法3 - ruby でサイトに接続してみる

curl が使えなかった場合、下記のスクリプトで、ヘッダの値を取得できます。

#!ruby
require 'net/http'
uri = <<URLHERE
http://www.ruby-lang.org/ja/man/?cmd=view;name=Net%3A%3AHTTP
URLHERE

dom,pth = uri.to_s.chomp.sub(/\A[\s\w]+:\/\/+/,"").split(/\//,2)
pth = "/" + pth.to_s
h = nil
Net::HTTP.version_1_2
Net::HTTP.start(dom) {|http|
  h = http.head(pth)
}
h.each do |key,val|
  key += ": "
  print key.ljust(16)
  puts  val
end

以上です。

Last updated 07.Sep.2007 [ Home ] [ Up ] [ 質問メール ]
Copyright © 2005-2006 Shigeru Konno All Rights Reserved..