CGIプログラムを設置してみよう

Report
情報処理III
wwwによる情報発信とサービス提供II
第7回
2014年11月6日
大塚 智宏
本日の予定
前回までの課題について
 CGIを学ぶ前の準備





CGIプログラムの基礎





静的Webと動的Web
CGIの概要
HTTPの基礎(復習)
CGIプログラムを作成してみよう
CGIプログラムを設置してみよう
CGIプログラムを実行してみよう
CGIにおける環境変数
今回の課題
前回までの課題について

第4回課題


採点結果の返却を行いましたので,ダウンロードして確認
してください
再提出の指示があった人は,11/12(水)までに再提出して
ください


第5回課題,第3回課題の再提出分


それまでに再提出がない場合,今回の採点結果で確定となります
採点が終了していないため,もう少しお待ちください
第6回課題

明日 11/7(金) 23:59 締切です
第3回課題

スライドの練習問題5問をそれぞれ解くためのプログラ
ムを作成せよ。
第3回課題の解答例(1)
1.
「プログラム例」 のプログラムを,入力された値が0の場合,負
の数の場合でそれぞれさらに別の出力をするように改造せよ。
print "input size: "
size = gets.to_i
if size < 0 then
puts "negative"
elsif size == 0 then
puts "zero"
elsif size < 10 then
puts "small"
elsif size < 20 then
puts "medium"
elsif size < 50 then
puts "large"
else
puts "extra-large"
end
# size が 0 より小さいならば
# そうでなく,size が 0 ならば
第3回課題の解答例(2)
2.
キーボード入力を数値として読み込み,それを西暦年として
その年がうるう年かどうかを判定するプログラムを作成せよ。



西暦年が4で割り切れる年はうるう年である。
ただし,西暦年が100で割り切れる年は平年である。
ただし,西暦年が400で割り切れる年はうるう年である。
print "input year: "
year = gets.to_i
if year % 400 == 0 then
puts "leap year"
elsif year % 100 == 0 then
puts "common year"
elsif year % 4 == 0 then
puts "leap year"
else
puts "common year"
end
# year が 400 で割り切れるなら
# そうでなく,100 で割り切れるなら
# そうでなく,4 で割り切れるなら
# それ以外の場合
第3回課題の解答例(3)
3.
1から100までの中からランダムに選んだ数を,ユーザに当て
てもらうプログラムを書け。






入力した数が当たるまで,何度も繰り返して入力を求めるものとする。
当たった場合は,メッセージを表示して終了する。
当たらなかった場合は,何らかのヒント ("too high" "too low" など)
を表示する。
範囲外の数が入力されたら警告を表示する。
ユーザが空行を入力したり,exit または quit と入力した場合は即座に
プログラムを終了させる。
なお,1から100までの乱数を得るには 1 + rand(100) という式を
使えばよい。
x = 1 + rand(100)
(次のスライドに続く)
# 1 から 100 までの乱数値(整数)を取得
第3回課題の解答例(3・続き)
print "input integer(1-100): "
while input = gets do
input.chomp!
if input == "" or input == "exit" or input == "quit" then
break
end
n = input.to_i
if n == x then
puts "Bingo!"
break
elsif n < 1 or n > 100 then
puts "input an integer between 1 and 100"
elsif n < x then
puts "too low"
elsif n > x then
puts "too high"
end
print "input integer(1-100): "
end
第3回課題の解答例(4)
4.
「プログラム例」 のプログラムを,結果を表示する部分もサブル
ーチンとして定義してそれを呼び出すように改造せよ。

その際,1回のサブルーチン呼出しで結果をすべて表示するバージョン,
サブルーチンを3回呼び出すバージョンの2種類作成せよ。
第3回課題の解答例(4・続き1)
### 1回のサブルーチン呼出しで結果をすべて表示するバージョン
# サブルーチン do_you_like の定義は 「プログラム例」 と同じなので略
def print_results(w1, a1, w2, a2, w3, a3)
puts "\nResults:",
" #{w1}: #{a1}",
" #{w2}: #{a2}",
" #{w3}: #{a3}"
end
what1 = 'programming'
what2 = 'playing the tennis'
what3 = 'listening to music'
ans1 = do_you_like(what1)
ans2 = do_you_like(what2)
ans3 = do_you_like(what3)
print_results(what1, ans1, what2, ans2, what3, ans3)
第3回課題の解答例(4・続き2)
### サブルーチンを3回呼び出すバージョン
# サブルーチン do_you_like の定義は 「プログラム例」 と同じなので略
def print_result(what, ans)
puts " #{what}: #{ans}"
end
what1 = 'programming'
what2 = 'playing the tennis'
what3 = 'listening to music'
ans1 = do_you_like(what1)
ans2 = do_you_like(what2)
ans3 = do_you_like(what3)
puts "\nResults:"
print_result(what1, ans1)
print_result(what2, ans2)
print_result(what3, ans3)
第3回課題の解答例(5)
5.
キーボード入力から2つの整数値を読み込み,2数の間にある
整数(2数も含む)の和を求めるプログラムを作成せよ。


その際,2数を引数として受け取って結果の値を返すサブルーチンを
作成し,それを利用するようにせよ。ただし,結果の出力はサブルーチン
内では行わないこと。
例えば 5 と 2 が入力されたら,5+4+3+2 で 14 となる。
def sum(x, y)
x, y = y, x
if x > y
# x > y ならば x と y の値を交換
(x + y) * (y – x + 1) / 2
end
print "input integer #1: "
n1 = gets.to_i
print "input integer #2: "
n2 = gets.to_i
puts "total: #{sum(n1, n2)}"
# x から y までの和を求める
サブルーチン (復習)

ある一連の処理に名前を付け,プログラムのどこから
でも再利用できるようにしたもの

以下の do_you_like というのがサブルーチン(の名前)

定義
呼出し
what のような変数を引数 (引き数,パラメータ) という
def do_you_like(what)
# 変数whatには呼出し元から渡された値が代入されている
while true do
print "Do you like #{what}? "
ans = gets.chomp
break if ans == 'yes' or ans == 'no'
puts "Please answer 'yes' or 'no'."
end
ans
# ansの値を戻り値として返す
end
ans1 = do_you_like('programming')
ans2 = do_you_like('playing the tennis')
サブルーチンによって何ができるか?

プログラムの 「モジュール化」 (部品化)





異なるパラメータに対する同じ処理の実行
処理内容に対する意味付け (名前付け,抽象化)
可読性,保守性の向上
コード量の削減
最適化やキャッシュメモリ等による処理速度の向上
呼出し
復帰
サブルーチン
サブルーチンと関数

言語によっては,「サブルーチン」 と 「関数」 とを区別する



関数: 処理の 「結果」 として値 (戻り値) を返す
サブルーチン: 処理を行うだけで,値を返さない (「手続き」 とも呼ぶ)
Rubyでは,両者の区別はない (正式には 「メソッド」 という)


Rubyのメソッドは必ず値を返すので,上記で言うところの関数としても
手続きとしても使うことができる
手続きとして使いたい場合は,呼出し側で戻り値を無視すればよい
def multiply(x, y)
# 「関数」 としての利用例
x * y
# 掛け算の結果(値)を戻り値として返す
end
def debug_print(val)
# 「手続き」 としての利用例
puts "DEBUG: the value is #{val}"
# putsの結果(値)を戻り値として返す (無意味)
end
関数とは

数学の y = f(x) の f と同じで,ある値 x を別の値 y に変換
する変換器,と捉えることができる


入力(x)に対応した出力(y)を返す機械,と言ってもよい
例: 入力された値の2乗を返す関数square
# 関数(サブルーチン)の定義
def square(x)
# 引数の「値」を x に代入
x * x
# 返り値(y)として,x*x の値を返す
end
# 関数の使用
a = 5
b = square(a)
5
8
x
square
y
25
64
好ましくない例

サブルーチン内で入力を受け取ったり結果を表示したりしている


そのような実装をする場合もあるが,あまり一般的ではない
「2数を引数として受け取って結果を返すサブルーチン」 などの指定に
そぐわない
def sum
# 引数を使用していない
# キーボードからの数値の入力を受け取る
a = gets.to_i
b = gets.to_i
# 2数の間にある数の和を求める処理
# 結果を表示
puts sum
# 意味のある返り値を返していない
end
Tips: 変数のスコープ

変数には,有効範囲 (スコープ) がある

スコープが異なっていれば,同じ名前の変数を使っても問題ない


ただ,可読性やメンテナンス性を損なうので,なるべく避けた方がよい
Rubyにおいて,変数のスコープは以下のようになる

その変数が宣言された (データの代入が行われた) 場所以降で,


宣言がサブルーチン内で行われていれば,そのサブルーチン内のみ
そうでなければ,ファイルの末尾まで
def subr1
x = 1
...
end
if cond1 then
x = 2
end
x = 3
この2つの x は別扱い
この2つの x は同じもの
静的Webと動的Web
静的ページと動的ページ(1)

静的Webページ (静的コンテンツ)


サーバ側にあらかじめ用意されたWebページのコンテンツ
(HTMLファイル等) が,そのままクライアントに送信される
ユーザやその環境,操作等によって内容が変わることがない


携帯電話やスマートフォン用サイトなど,ユーザ側の端末やブラウザ
の種類によってページが切り替わるケースはある
「読む」 「見る」 ためのWebページ
HTTPリクエスト
http://hoge.com/sample.html
インター
ネット
HTML
コンテンツ
Webサーバ
HTTPレスポンス
Web
クライアント
静的ページと動的ページ(2)

動的Webページ (動的コンテンツ)

ユーザの操作や入力内容,環境などに応じて,コンテンツが
アクセスのたびに生成される


CSSや動画による 「動き」 だけの場合は動的ページとは呼ばない
アプリケーションのような使い勝手を提供しているものも多く,
一般に 「Webアプリケーション」 と呼ばれる

「使う」 「操作する」 ためのWebページ
exe
呼出し
・実行
HTTPリクエスト
http://hoge.com/sample.cgi
フォーム等によるユーザ要求の送信
プログラム
インター
ネット
出力
HTML
コンテンツ
Webサーバ
HTTPレスポンス
Web
クライアント
動的Webページの例

動的Webページを用いたさまざまなサービス










検索エンジン
Webメール
インターネット掲示板(BBS)
Blog / Twitter / Wiki / SNS / CMS
各種ポータル / 口コミサイト等のCGM
オンラインショッピング / ネットオークション
インターネットバンキング / オンライントレード
文書・動画共有 / オンラインストレージ
地図 / 位置情報サービス
いずれも,現在のWebでは当たり前のサービスとなっている

これらのWebアプリケーションの普及が現在のWebそのものの発展を
支えていると言える
動的Webページの実現
ユーザがページにアクセスした際に,コンテンツを生成
するための 「プログラム」 を実行する必要がある
 プログラムの実行場所の違いにより,動的Webを実現
するための技術は以下の2種類に分類される


サーバサイド


クライアントサイド


Webサーバ上でプログラムを実行
クライアント上でプログラムを実行
利用局面が異なるため,両方の技術を併用するケース
も珍しくない
サーバサイドの動的Web(1)

クライアントからのリクエスト(HTTP)があった際に,サーバ上で
コンテンツを生成するための外部プログラムを実行


サーバは,リクエストに含まれるURIなどの情報からプログラムの呼出し
が必要かどうかを判断する
プログラムが生成したコンテンツは,リクエストに対するレスポンスとして
クライアントに送信される
exe
呼出し・実行
プログラム
インター
ネット
出力
HTML
HTTPリクエスト
http://hoge.com/sample.cgi
Webサーバ
HTTPレスポンス
コンテンツ
Web
クライアント
サーバサイドの動的Web(2)

主な特徴




データベースとの連携等で大規模データや認証データを扱う必要が
ある場合,高負荷な処理が要求される場合などに適している
セッションの状態を維持するためには,HTTP cookie等の補助的な
技術を利用する必要がある
多くの場合,複数ユーザ(セッション)の処理を同時に行う必要がある
ため,データの取扱いには注意が必要
該当する主な技術




CGI / SSI / PHP
ASP / ASP.NET
Java Servlet / JSP
ColdFusion
クライアントサイドの動的Web(1)

あらかじめコンテンツ中にプログラムのコードや実行形式を埋め
込んでおき,クライアント側でそれを実行


Webブラウザが直接実行するもの(JavaScript等)や,ブラウザとは
別のアプリケーションとして実行されるもの(Adobe AIR等)がある
クライアント側に対応する実行環境が整っている必要がある
HTTPリクエスト
http://hoge.com/sample.html
HTML
+JS
実行
インター
ネット
HTML
Webサーバ
プログラムが
埋め込まれた
コンテンツ
HTTPレスポンス
JS
出力
Web
クライアント ブラウザ内などで
プログラムを処理
クライアントサイドの動的Web(2)

主な特徴




サーバサイドの動的Web技術と組み合わせて利用することで,ユーザ
インターフェース(UI)の向上等を図ることができる
Ajax等を用いた高機能なWebアプリケーションの登場で,近年注目が
高まっている
ブラウザの機能を拡張することで,柔軟で表現力の高いUIを持つWeb
アプリケーション (リッチインターネットアプリケーション,RIA) を開発
可能なフレームワークが多数登場している
該当する主な技術




JavaScript (JS) / Ajax
Adobe Flash / Microsoft Silverlight / JavaFX
Adobe AIR / Microsoft ClickOnce / Java Web Start
HTML5 (の一部)
CGIの概要
CGIとは(1)

サーバサイドの動的Web技術の一つ



「Common Gateway Interface」 の略
動的Webページ構築のための仕組みとしては最初に開発
されたもの (1993年)
Webサーバと外部プログラムとの連携方法を定義



Webサーバから外部プログラムを呼び出す方法
プログラムの処理結果をWebサーバが受け取る方法
CGIを介して実行されるプログラムを 「CGIプログラム」
と呼ぶ

「CGI」 自体はプログラムのことを指すわけではない
(が,よく混同される)
CGIとは(2)

外部プログラムを記述する言語は何でもよい



以前は,CGI = Perl のような誤解が広まるほどPerlが
多く用いられていた
最近はPythonやRubyも広く使われている
リクエストが来るたびにプログラムを呼び出すため,
サーバの負荷が大きくなる傾向がある

そのため,比較的軽量で,処理速度がさほど重要でない
アプリケーションに用いられることが多い

掲示板,アクセスカウンタ,Blog,Wiki など
CGIの利点

単純であるため習得が比較的容易で,動的Webの仕組みを
理解するのに適している



ほぼ全てのWebサーバが対応しており,環境を選ばない


本質的でない細かいことを学ぶ必要があまりない
他の動的Web技術を学ぶための基礎にもなる
特にPerlによるCGIは,レンタルサーバ等でも大抵利用可能
基本的にどんなプログラミング言語でも使える


適・不適はあるが,好きな言語でプログラムを実装することができる
複数の言語を組み合わせることも可能
CGIの基本的な仕組み
1.
クライアントがCGIプログラムに対応するURIにアクセス

2.
3.
WebサーバはCGIへのアクセスであることを確認したら,該当
するCGIプログラムを起動し,ユーザからのデータを渡す
プログラムが実行され,処理結果(出力)がサーバに返される

4.
通常はフォーム等を用いてユーザの要求(データ)を送信する
通常はこの出力がHTML形式となっている
サーバは,出力をレスポンスとしてクライアントに送信
exe
呼出し・実行
データ入力
HTTPリクエスト
http://hoge.com/sample.cgi
フォーム等によるユーザ要求の送信
CGIプログラム
出力
HTML
コンテンツ
インター
ネット
Webサーバ
HTTPレスポンス
Web
クライアント
CGIプログラムの呼出し

HTTPリクエストがCGIプログラムへのアクセスであるかどうか
は,サーバ側でURIのパス名などから判断する

典型的な例



ファイル名の拡張子で判断: http://hoge.com/sample.cgi
ディレクトリ名で判断: http://hoge.com/cgi-bin/sample
CGIへのアクセスであることを確認したら,リクエストされたファイルを
CGIプログラムとして起動し,ユーザからの入力データを渡す

上記の例では,「sample.cgi」 や 「sample」 をプログラムとして起動
exe
呼出し
・実行
HTTPリクエスト
http://hoge.com/sample.cgi
フォーム等によるユーザ要求の送信
CGIプログラム
Webサーバ
インター
ネット
Web
クライアント
CGIプログラムの出力

CGIプログラムは実行結果としてHTMLを出力し,それがHTTP
レスポンスとしてクライアント側に送信される



場合によっては他のデータ (画像データ等) を出力することもある
ステータス行やHTTPヘッダはサーバが再構築してから送信する
プログラムの実行で何らかの問題が発生した場合,「Internal Server
Error」(ステータスコード500) がレスポンスとして返される

プログラムの起動失敗,文法エラー,実行時エラー,出力形式の不備等
exe
CGIプログラム
出力
HTML
コンテンツ
インター
ネット
Webサーバ
HTTPレスポンス
Web
クライアント
CGIプログラムの実例

掲示板 (リンク,ソースコード)



画像アップローダ (リンク,ソースコード)



画像(GIF,JPEG,PNG)のみをアップロード可能
新着20件の画像へのリンクを表示,古いものは自動的に削除
三目並べ (リンク,ソースコード)




大した機能はない簡単な掲示板
新着20件の記事を表示,古い記事は自動的に削除
いわゆる 「○×ゲーム」
プレイヤーは先攻(○)固定
コンピュータ側はあまり賢くない
この程度のものを作れるようになるのが一つの目標
HTTPの基礎(復習)
Webの基本的な構造

Webの3要素



URI: 情報の 「場所」 を表現
HTML: 情報の 「中身」 を表現
HTTP: 情報の 「交換方式」 を定義
HTMLファイル
sample.html
<html>
<head>
<title>Sample</title>
</head>
<body>
<p>Hello!</p>
</body>
</html>
Web
サーバ
www.hoge.com
URI (URL)
ユーザエージェント
(Webブラウザなど)
http://www.hoge.com/sample.html
Hello!
HTTP
(HyperText Transfer Protocol)
Web
クライアント
インターネット
PC,携帯電話など
Webページ閲覧時の処理の流れ(1)
1. ユーザがWebブラウザに対し,閲覧したいページの
URIを伝える


URIを打ち込む,ブックマークを開く,リンクを辿る,等
例として http://www.keio.ac.jp/index.html を仮定
2. ブラウザは,ホスト www.keio.ac.jp のIPアドレスを
DNSを参照(正引き)して取得する


実際のDNSの参照は,OSが補助する場合が多い
結果として 131.113.134.20 を得る
3. ブラウザは,ホスト 131.113.134.20 の80番ポート
に対してTCPの接続を確立する


特に指定がない場合,HTTPではTCPの80番ポートを使う
サーバ側では,Webサーバプログラムが呼び出される
Webページ閲覧時の処理の流れ(2)
4. ブラウザとWebサーバは,確立されたTCP接続上で
HTTPプロトコルのメッセージをやり取りする
1. ブラウザが,取得したいリソースの絶対パス(/index.html)
をリクエストメッセージとして送る
2. サーバは,対応するリソース(HTMLファイル)をレスポンス
メッセージとして送り返す
3. ブラウザは受信したHTMLを解析し,追加で必要なリソース
(外部CSSや画像ファイル等)があればさらにリクエストメッ
セージを送って取得する
5. ブラウザは,取得したリソース群(HTML+CSS等)を
解析し,レンダリングして画面に表示する

実際には,受信したリソース群はキャッシュとして一旦メモリ
やディスクに保存されるのが普通
HTTP (HyperText Transfer Protocol)

Webにおいて,ブラウザとWebサーバの間でHTML等
のコンテンツの送受信に用いられるプロトコル



リクエスト-レスポンス型(後述)のプロトコル
トランスポート層にはTCPを用い,サーバ側はデフォルトで
80番ポートを使用する
HTTPのバージョン


HTTP/0.9 (1989年)
HTTP/1.0 (1996年,RFC 1945)


ヘッダの導入等,0.9から大幅に拡張された
HTTP/1.1 (1997年,RFC 2068)


キープアライブやバーチャルホスト機能等,1.0をさらに拡張
その後改訂されてRFC 2616 (1999年) となっていたが,2014年
6月に約15年ぶりに改訂され,RFC 7230~7235 となった
クライアント-サーバモデル

通信を行うコンピュータを 「サーバ」 と 「クライアント」
に分類し,クライアントがサーバに要求を送信して
サーバがそれに応答を返す形で処理を行う通信方式

この方式で処理が行われるプロトコルは 「リクエスト-レスポ
ンス型」 のプロトコルと呼ばれる


HTTP,SMTP等,多くのプロトコルがこの方式を採用している
他の方式としては,ピアツーピア(P2P)がある
<html>
<head>
<title>Sample</title>
</head>
<body>
<p>Hello!</p>
</body>
</html>
Hello!
要求(HTTPリクエスト)
Web
サーバ
Web
クライアント
応答(HTTPレスポンス)
HTTPリクエスト

クライアントからサーバに送信する要求メッセージ


リクエスト行,(複数の)ヘッダ,ボディで構成される
リクエスト行 = 「メソッド URI バージョン」


ヘッダ = 「ヘッダ名: 内容」



リクエストの内容,および要求対象のリソース(ファイル)を示す
リクエスト内容やクライアントに関する追加情報
改行で区切って複数(必要なだけ)記述できる
ボディは特定のメソッドでデータを送信するのに使われる
リクエスト行
ヘッダ(必要なだけ)
・・・
<空行>
ボディ(必要な場合)
・・・
GET /index.html HTTP/1.1
Host: www.keio.ac.jp
...
リクエスト行
ヘッダ
空行
メソッド

HTTPリクエストの種類を表す識別子

GET: リソースの取得



HEAD: ヘッダのみの取得




ボディとしてデータを送信し,URIで指定したリソースに渡す
入力データをCGIプログラム等に処理させる場合に使われる
その他 (詳細は略)


GETと同様リソースを要求するが,ヘッダのみが返送される
ページの更新状況のみを確認したい場合などに使われる
POST: データの送信と処理要求


最も頻繁に使用されるメソッド
URIに含める形でデータを送信することも可能 (クエリ文字列)
PUT,DELETE,OPTIONS,TRACE,CONNECT,PATCH
メソッドは全て大文字で書かなければならない点に注意
HTTPレスポンス

サーバからクライアントに送信する応答メッセージ


ステータス行,(複数の)ヘッダ,ボディで構成される
ステータス行 = 「バージョン ステータスコード 説明句」


ヘッダ = 「ヘッダ名: 内容」



レスポンスの意味 (成功,失敗,エラー等) を表す
レスポンス内容やサーバに関する追加情報
改行で区切って複数(必要なだけ)記述できる
要求されたリソースはボディ部分に格納される
ステータス行
ヘッダ(必要なだけ)
・・・
<空行>
ボディ(必要な場合)
・・・
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 795
...
<!DOCTYPE html>
...
ステータス行
ヘッダ
空行
ボディ
ステータスコード(1)

HTTPレスポンスの意味を表す3桁の番号

対応する説明句とセットでステータス行に含められる


「HTTP/1.1 404 Not Found」 等
100の位の値によって5種類に分類される





1XX:
2XX:
3XX:
4XX:
5XX:
情報提供
成功
転送
クライアント側のエラー
サーバ側のエラー
ステータスコード(2)

主なステータスコード

200 OK



301 Moved Permanently



「リクエストは成功した」
要求されたリソースがボディとして送信される
「リソースは恒久的に移動した」
Locationヘッダで移動先が通知され,通常はブラウザが移動先を
指定して再度リクエストを行う (ページは自動的に転送される)
304 Not Modified


「リソースは更新されていない」
If-Modified-Sinceヘッダによる条件付きGETにおいて,リソースが
更新されていない場合など
ステータスコード(3)

主なステータスコード(続き)

401 Unauthorized



403 Forbidden



「サーバが実行を拒否した」
閲覧権限のないリソースを要求した場合など
404 Not Found



「リソースの参照には認証が必要」
認証情報を付加して再度リクエストを行う必要がある
「リソースが存在しない」
URIが間違っている場合など
500 Internal Server Error


「サーバの内部エラー」
CGIプログラムの実行に失敗した場合など
ヘッダ

HTTPリクエストやレスポンスにおいて,さまざまなメタ
情報をやり取りするためのフィールド

1行に1つずつ,「ヘッダ名: 内容」 の形で必要な数だけ記述


ヘッダ群の後ろ(ボディの前)には空行を入れる
以下の4種類に分類される

リクエストヘッダ
 HTTPリクエストで使用され,リクエストやブラウザに関する情報を送る

レスポンスヘッダ
 HTTPレスポンスで使用され,レスポンスやサーバに関する情報を送る

エンティティヘッダ
 レスポンスやPOSTメソッドによるリクエストなどで使用され,転送される
リソース(ボディ)に関する情報を送る

一般ヘッダ
 リクエスト/レスポンスの両方で使用され,上記以外のさまざまな情報を
送る
主なリクエストヘッダ(1)

Host





User-Agent




リクエストURIのホスト名 (ポート番号が80以外の場合はそれも指定)
例: Host: www.keio.ac.jp
例: Host: proxy.example.com:8080
リクエストで唯一の 「必須」 ヘッダ
ユーザエージェント(UA,ブラウザ)の種類やバージョン
例: User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:30.0)
Gecko/20100101 Firefox/30.0
UAによるページの振り分けやスタイルの切替え等に利用される
Referer



リクエストURIの参照元ページのURI (リンク元)
例: Referer: http://www.keio.ac.jp/
アクセス解析などに利用される
主なリクエストヘッダ(2)

If-Modified-Since




条件付きリクエスト (指定時刻以降にリソースが更新されている場合
のみリソースが返送される)
例: If-Modified-Since: Wed, 2 Jul 2014 07:23:31 GMT
更新されていない場合,304 Not Modified が返される
Last-Modified との組合せでキャッシュの制御に利用される


Range



キャッシュ制御では,ETag と If-None-Match の組合せもよく使われる
リソースの一部のみを要求
例: Range: bytes=512- (最初の512バイトを除いた残りの部分)
Authorization


認証情報 (認証方式によって内容は異なる)
例: Authorization: Basic bmV0Om5ldDEyMwo=
主なレスポンスヘッダ

Server



Location




Webサーバソフトウェアの種類やバージョン
例: Server: Apache/2.4.9 (Unix)
移動したリソース等の新しい場所を示す
例: Location: http://www-new.example.com/
301 Moved Permanently 等に付随して送信される
WWW-Authenticate



認証を要求し,認証方法とそのパラメータを指定
例: WWW-Authenticate: Basic realm="Member Only"
401 Unauthorized に付随して送信される
主なエンティティヘッダ

Content-Type



Content-Length



ボディとして送信されるリソースのメディアタイプを示す
例: Content-Type: text/html; charset=utf-8
ボディ部分の長さ(サイズ)をバイト単位(10進数)で示す
例: Content-Length: 795
Last-Modified



リソースの最終更新時刻(日時)
例: Last-Modified: Wed, 2 Jul 2014 07:23:31 GMT
If-Modified-Since で時刻を指定する際などに利用される
主な一般ヘッダ

Date



Connection




メッセージが作成された日時
例: Date: Thu, 3 Jul 2014 16:43:46 GMT
TCP接続に関するオプションを指定
例: Connection: close
HTTP/1.1 ではキープアライブ(次回説明)がデフォルトのため,明示
的に接続を終了する際はリクエストで上記のように指定する
Cache-Control


クライアント側のキャッシュ制御に関するオプションを指定
例: Cache-Control: no-cache, no-store
その他


HTTPの応用的な話題や,HTTPの通信をトレースする方法に
ついては,情報処理II(春学期)第12,13回の資料を参照
TCP/IP,HTTPに関する参考サイト

RFC 7230~7235 (HTTP/1.1)







HTTP入門


http://tools.ietf.org/html/rfc7230
http://tools.ietf.org/html/rfc7231
http://tools.ietf.org/html/rfc7232
http://tools.ietf.org/html/rfc7233
http://tools.ietf.org/html/rfc7234
http://tools.ietf.org/html/rfc7235
http://www.tohoho-web.com/ex/http.htm
3 Minutes Networking

http://www5e.biglobe.ne.jp/%257Eaji/3min/
CGIプログラムを
作成してみよう
CGIプログラムを公開するにあたって

HTMLファイルのみの公開とは違い,セキュリティ的な
危険を伴う行為なので充分注意する

作成中やテスト中のプログラムはできる限り公開しない



使わなくなったプログラムやバックアップファイルは消しておく


エディタ等が自動的にバックアップファイルを作成する場合がある
ため,公開領域上でファイルを直接編集するのは避ける
Web等で紹介されているプログラムを無闇に使わない



サーバ上でテストする場合はアクセス制限をかける
アクセス元の制限やパスワードをかける方法などは後ほど紹介
セキュリティが考慮されていないものも多く存在する
少なくとも,内容をちゃんと理解できるまで勉強してから使う
ユーザの入力を受け取るプログラムでは,意図しない文字
等が入力に含まれていないか必ずチェックする

クライアントが送信したデータを信用してはいけない
CGIプログラムの出力内容

HTTPレスポンスのうち,ステータス行を除いたものを
出力する,と考えればよい

ヘッダは通常 Content-Type のみを指定すればよく,他の
ヘッダはWebサーバが自動的に生成してくれる


特殊なケースとして,Locationヘッダでの転送先URIの指定や,
Statusヘッダでの 「200 OK」 以外のステータスコードの指定も可能
Content-Type,Location,Status のいずれかのヘッダを必ず
指定する必要がある
HTTPレスポンス
ステータス行
ヘッダ
・・・
<空行>
ボディ(コンテンツ)
・・・
CGIプログラムの出力
Content-Type: text/html
ヘッダ
空行
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
...
コンテンツ
RubyによるCGIプログラムの例
#!/usr/local/bin/ruby –w
print <<'EOT'
Content-Type: text/html; charset=us-ascii
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="us-ascii" />
<title>CGI Sample</title>
</head>
<body>
<p>
This is a sample CGI program.
</p>
</body>
</html>
EOT
RubyによるCGIプログラムの例(解説)

Ruby等のインタプリタ方式の言語でCGIプログラムを作成する
場合,1行目に起動するインタプリタプログラムの指定を行う


shebang (シェバン) と呼ばれ,必ず1行目に記述する
ITCの環境でRubyを使う場合は,常に以下のように指定
#!/usr/local/bin/ruby –w

出力部分は 「ヒアドキュメント」 と呼ばれる方法を使っている

printやputsを何度も使うよりプログラムがすっきりする (後で解説)
print <<'EOT'
Content-Type: text/html; charset=us-ascii
<!DOCTYPE html>
<html lang="en">
...
</html>
EOT
Windows上での実行結果

HTMLファイルの内容を表示したような出力になる


最初にContent-Typeヘッダと空行が追加されている
Windows上で実行する場合,shebangはコメントとして無視される
Tips: ヒアドキュメント

複数行にわたる文字列を出力するのに便利な方法

putsや " " を何度も使うのを避けることができ,見やすくなる
puts "<head>"
puts "<title>CGI Sample</title>"
puts "</head>"
print <<'EOT'
<head>
<title>CGI Sample</title>
</head>
EOT


「EOT」 の部分は任意のワードでよいが,慣習的に EOT (End of Text)
や EOS (End of String),EOF (End of File) などがよく使われる
'EOT' の代わりに "EOT" とすると文字列中で式展開が使える
CGIプログラムを設置する前に…

Windows上で実行し,文法エラー等がないかチェックしておく

-cオプションで文法チェックのみを行うこともできる (実行はされない)
CGIプログラムを
設置してみよう
CGIプログラムの設置手順
1.
テキストエディタ等でCGIプログラムを作成して保存

2.
ITCの環境では,ファイル名を 「~.cgi」 とする
作成したプログラムをWebサーバに転送 (アップロード)

ITCの環境では,SCPまたはSFTPプロトコルを利用する


3.
春学期にやったのと同じ方法でOK (WinSCPを使用)
アップロード用サーバ upload.user.keio.ac.jp 上のホームディレクトリ内
「public_html」 ディレクトリ以下に転送する
アップロードしたプログラムファイルのアクセス権限を変更し,
サーバ上で実行できるようにする

WinSCP上で操作可能
CGIプログラムを設置してみよう(1)

WinSCPを起動

スタートメニュー ⇒ 「すべてのプログラム」 ⇒ 「WinSCP」 ⇒
「WinSCP」
CGIプログラムを設置してみよう(2)

アップロード用サーバにログイン

以下の各項目を入力して 「ログイン」 を選択



ホスト名: upload.user.keio.ac.jp
ユーザ名: ITCアカウントのユーザ名
パスワード: 同パスワード
CGIプログラムを設置してみよう(3)

そのサーバへの初回接続時は以下の警告が出る

出た場合は 「はい」 を選択


春学期の授業を履修した人は,おそらく出ないはず
2回目以降に出た場合は,以下のいずれかが考えられる



機器の入れ替え等でサーバが別のマシンになった
悪意ある人が偽のサーバを立てており,そこに接続しようとしている
個人環境に保存されたサーバの情報が,何らかの理由で失われた
CGIプログラムを設置してみよう(4)

ログインに成功した状態


ウィンドウの左側がローカルPC (Windows)上の,右側が
サーバ上のファイル選択画面になっている
サーバ側の 「public_html」 がWeb公開用ディレクトリ
CGIプログラムを設置してみよう(5)

「public_html」 に移動


ウィンドウ右側の 「public_html」 をダブルクリック
public_htmlディレクトリの内容が表示される


春学期の授業を履修した人は,ファイルが残っているかも
「..」 は1つ上の階層 (親ディレクトリ) を表す
CGIプログラムを設置してみよう(6)

CGIプログラム設置用のディレクトリを作成

右側を選択した状態で 「F7 ディレクトリの作成」 をクリック




「F7」キーを押すのでも同じ
「新規フォルダ名」 に 「cgi-bin」 と入力して 「OK」
ウィンドウ右側に 「cgi-bin」 ディレクトリが表示される
この作業は初回のみでよい
CGIプログラムを設置してみよう(7)

「.htaccess」 ファイルの設置



「cgi-bin」 ディレクトリに移動し,「ファイル」 メニュー ⇒
「新規」 ⇒ 「ファイル」 を選択
「ファイル名を入力」 に 「.htaccess」 と入力して 「OK」
開いたウィンドウに以下の1行を入力し,左上から2番目の
保存ボタンを押して保存してから閉じる
Options +ExecCGI




パスワードを要求されるのでITCアカウントのパスワードを入力
ウィンドウ右側に 「.htaccess」 ファイルが作成されたことを確認
この作業も初回のみでよい
「.htaccess」 はWebサーバプログラム 「Apache」 の設定
ファイルの一つで,設置したディレクトリごとにWebサーバの
動作をカスタマイズすることができる
CGIプログラムを設置してみよう(8)

「cgi-bin」 上にプログラムファイルをアップロード


ウィンドウ左側で転送したいファイルを探して選択
右側へドラッグ&ドロップ,または 「F5 コピー」 をクリック


「F5」キーを押すのでも同じ
確認のウィンドウが出るので,「コピー」 をクリック
CGIプログラムを設置してみよう(9)

アップロードしたプログラムに実行権限を付与


(ウィンドウ右側で)アップロードしたファイルを選択し,「F9
プロパティ」 をクリック
表示されたウィンドウで,「所有者」 の 「X」(実行権限) に
チェックを入れて 「OK」
WinSCPについての補足(1)

その他の操作



コピーの方向を逆にすれば,サーバからローカルPCに
ファイルをダウンロードできる
複数のファイルをまとめてコピーしたり,ディレクトリごと
コピーしたりすることもできる
他にも,ファイルやディレクトリの削除,移動,名前の変更,
編集などが可能


ただし,サーバ上のファイルを直接編集するのは避けた方がよい
接続先サーバの情報は保存しておくこともできる

起動時メニューの 「保存したセッション」 で管理
WinSCPについての補足(2)

自宅等のPCからアップロードする場合

まず,以下からWinSCPをダウンロードしてインストール

http://winscp.net/
 ダウンロードのページは英語だが,インストール時に日本語を選択可



2014年11月6日現在の最新版は 「5.5.6」
あとはITCの環境での操作とほとんど同じ
Macの場合は 「Cyberduck」 がおすすめ

http://cyberduck.ch/
CGIプログラムを
実行してみよう
CGIプログラムの実行

設置したCGIプログラムにブラウザからアクセスするとサーバ側
でプログラムが実行され,出力内容(HTML)がクライアント
(ブラウザ)へ送信される

先ほどの例のようにITCの環境でホームディレクトリ以下の
public_html/cgi-bin/ に設置した場合,以下のURIにアクセス

http://user.keio.ac.jp/~ユーザ名/cgi-bin/~.cgi
出力内容の確認

CGIプログラムの実行結果(出力)は,通常のHTMLファイルと
同じようにHTTPレスポンスとしてクライアントに送信される


ページのソースを表示してみると,確かにCGIプログラムが出力した
HTMLの内容になっていることが分かる
クライアント側からは,CGIによる動的ページなのか,もともと置いてある
HTMLファイル (静的ページ) なのかは判別できない

URIなどからある程度想像は付くが,本当にそうかどうかは分からない
実行に失敗した場合

プログラムや実行環境などに何らかの不備があった場合,以下
のようなエラーが表示される


HTTPのステータスコードが 「500 Internal Server Error」 となる
ブラウザからはエラーの内容を(簡単には)確認できない


確認する方法については次回以降に紹介予定
これが出てしまったら,プログラムの内容や設置状況の確認が必要



Windows上で実行した際にもエラー等が出ていなかったか?
Content-Typeヘッダや直後の空行を正しく出力しているか?
アップロードしたプログラムに実行権限は設定されているか?
CGIにおける環境変数
環境変数とは

OSが提供するデータ共有機能の一つ

主に,プログラムの挙動を変更するために用いられる




UNIXの環境変数: HOME,PATH,SHELL,PWD,等
Windowsの環境変数: PATH,PATHEXT,TEMP,等
多くのプログラミング言語で,プログラムの実行中にOSの
環境変数にアクセスする手段が提供されている
Rubyでは,ENV というハッシュを介してアクセスする


環境変数の名前と値 (いずれも文字列) がそれぞれENV
ハッシュのキーとデータになっている
例えば,PATH という環境変数の値は ENV["PATH"] に
よって取得できる
環境変数の参照
# すべての環境変数の名前と値を,名前の辞書順に表示
ENV.keys.sort.each do |name|
value = ENV[name]
puts "#{name}\n\t#{value}"
end
CGI環境変数

CGIでは,通常の環境変数に加えてWebサーバが取得した
HTTPヘッダ等の情報を環境変数として提供しており,CGI
プログラムから参照できる


サーバやクライアントの情報,CGI環境の情報を提供するものもある
主なCGI環境変数









HTTP_HOST
HTTP_REFERER
HTTP_USER_AGENT
REMOTE_ADDR
REQUEST_METHOD
REQUEST_URI
QUERY_STRING
CONTENT_TYPE
CONTENT_LENGTH
Hostヘッダ (リクエストURIのホスト名)
Refererヘッダ (リンク元ページのURI)
User-Agentヘッダ (ブラウザの種類)
クライアントホストのIPアドレス
HTTPリクエストのメソッド (GET,POST等)
リクエストURIのパス (/cgi-bin/~.cgi 等)
リクエストURIのクエリ文字列 (次回説明)
リクエストボディのメディアタイプ
リクエストボディの長さ(バイト)
CGI環境変数の利用例
#!/usr/local/bin/ruby –w
# coding: utf-8
print <<'EOT'
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>クライアント情報</title>
</head>
<body>
<p>
EOT
(次のスライドへ続く)
CGI環境変数の利用例(続き)
# 環境変数の値を表示
puts "あなたは,ホスト #{ENV["REMOTE_ADDR"]} からブラウザ
「#{ENV["HTTP_USER_AGENT"]}」 によってこのページにアクセスして
います。"
print <<'EOT'
</p>
</body>
</html>
EOT
今回の課題
課題

環境変数の一覧(名前および値)をHTMLで表示する
CGIプログラムを作成し,ITCの環境に設置して動作を
確認せよ。

表示形式は自由だが,見やすくなるように工夫せよ。



pre要素を使う,箇条書きや定義リストを使う,表にする,など
CSSを利用しても構わないが,評価対象とはしない。あくまでHTML
の範囲内で表示を工夫すること。
出力がHTMLとして正しいかどうかをバリデータを用いて
確認すること。


W3Cのバリデータで,URIを指定する方式でチェックすればよい。
http://validator.w3.org/
課題(続き)

提出物

以下をZipファイルにまとめたもの


プログラムの設置先URIを記載したテキストファイル
(設置したものと同じ)プログラムファイル
 コメントとして処理内容の説明を適宜入れること

提出期限


11月14日(金) 23:59
keio.jp 「授業支援」 上で提出

similar documents