WWW server "SilkWeb" page (補足のページ(?))
[ もどる ]
このページでは 〆(^^) 作の WWW server SilkWebの解説を行っています。
付属ドキュメントの改訂版といってもいいっしょ。
このページで(にかぎらず)分かりにくい場合は 連絡下さい。
で, ダウンロードはこちらからどーぞ。関係のページもあります。
でもまあ, これって多くの人には関係のない話だろうけどね (T_T
だいたい WWW server なんか立ち上げる人ってそんなにいるもんじゃない。
ましてや, 他のサーバーの方が高速なうえ機能も高いし, その上安定性もばっちり
・・・バッチソって書いたら今風なんかな (^^)\(バキ☆)
これを動かす目的は動作を知る事だと思えば, 多少のアレには目をつぶって … (←アレって?)
このページのイメージは ハエ取り草, じゃなくって えーと, 女郎蜘蛛です。
例えば, Webブラウザから存在しないページをアクセスされた場合, Webサーバーはコード 404と 少しばかりのメッセージを返します。
少し親切なサーバーは, ヒントとしてどこかへのリンクを出す場合もあります。
また, Webブラウザでアクセスしている人を不安がらせないようにするためか, アニメーション画像と共に親切丁寧に その状態を知らせるのもあります。
SilkWebでは, エラーメッセージを生成する部分を別に用意することで, そうした用途に対応できます。もちろんアニメーション画像を用意すればそれを表示できます。
プログラム名は SlkErr.cmdです。このプログラムが存在しない場合, エラーメッセージは質素なものになります。
/* サンプルのエラーメッセージプログラム (SlkErr.cmd) */ options 'ETmode' parse arg scd msg select when scd == 301 then txt = 'ずっと移動' when scd == 302 then txt = '一時的に移動' when scd == 303 then txt = '???' when scd == 304 then txt = '変更なし' when scd == 401 then txt = '認証' when scd == 402 then txt = '???' when scd == 403 then txt = '禁止' when scd == 404 then txt = 'ない' when scd == 501 then txt = '実装されていない' otherwise txt = 'scd='scd ',msg="'msg'"' end res = '<html><head><title>Error' scd'</title></head>', '<body bgcolor=white>'txt'<br>'msg'</body></html>' return res |
このままではあまり意味がありませんが, これを見栄えよく変更することで, そのサイトに合った雰囲気の画面を作り出す事ができます。
エラーを起こさないと見る事はできませんが・・
作成したプログラムは, SilkWeb のシステムと同じ場所に置いておくとよいでしょう。 そこに存在すれば, 自動的に呼び出されます。
SlikWeb には, 現在(Ver 1.3)のところ 2つのサンプル CGIがあります。
この使い方を少しばかり説明します。
準備としては, まず SilkWebサーバーを立ちあげておきます。
http://127.0.0.1/cgi/SlkBBS
この BBSでは件数が多くなると, 別ファイルに保存されます。[過去ログ]とは, それを見るためのものです。
これらの情報が記録されているファイルは, テキストファイルです。
誤った情報を削除したりする場合には, テキストエディターを使う事ができます。
http://127.0.0.1/cgi/SlkFilt
http://www.ibm.co.jp/pspjinfo/
CGIのプログラムを動かす場合, いくつかの方法があります。
まずは, 入力側。CGIプログラムは次の方法で情報を得る事ができます。
環境変数 内容 REQUEST_METHOD GET によるものか POST によるものかということ。どちらかの文字列が入っている。 SCRIPT_NAME 例えば次のようなもの /cgi/web-bbs.cmd SERVER_SOFTWARE サーバー名。'SilkWeb(RxHTTPd)/1.2' が入る。'/' の後はバージョンなので変化するかもしれない。 SERVER_PROTOCOL 'HTTP/1.0' SERVER_ADDR 接続を受けた IP アドレス (例えば '127.0.0.1' など) SERVER_PORT 通常は 80。ただし設定にもよる。 REMOTE_ADDR 接続してきたクライアントの IP アドレス PATH_INFO 例えば cgi/a/b/c の時の "/a/b/c" PATH_TRANSLATED PATH_INFOの前に 構成ファイルの WWWrootをつけたもの QUERY_STRING 要求行の '?'以降の文字列 (エンコードされている)。POST の場合は, ここではない。 HTTP_USER_AGENT 要求ヘッダーの 'User-Agent:' (例えば 'Mozilla/3.14 [ja] (OS/2; I)') HTTP_ACCEPT 要求ヘッダーの 'Accept:' (例えば 'image/gif, image/jpeg, */*') HTTP_REFERER 要求ヘッダーの 'Referer:' (どこからたどってきたかを表す) CONTENT_TYPE 要求ヘッダーの 'Content-Type:' (例えば 'application/x-www-form-urlencoded') CONTENT_LENGTH 要求ヘッダーの 'Content-Length:'
その次の引数は, POSTメソッド時の情報の一部です。 エンコードされたままになっているので, 場合によってはデコードが必要。 通常は, これだけで処理可能ですが, multipart での POSTの場合, 後に述べる方法で続きを読み込む必要があります。
WWWroot 同名の 構成ファイルの項目 WelPage 同名の 構成ファイルの項目 ServName 環境変数の SERVER_SOFTWAREと同じ内容 ProtoVer 環境変数の SERVER_PROTOCOLと同じ内容 sk この要求で使用しているソケットの番号
〜 parse arg Env, params if left(params, 1) == ';' then qs = HexDcoStr(GetCGIEnv('QUERY_STRING')) else qs = HexDcoStr(params) sk = word(Env, wordpos('sk', Env) +1) ln = GetCGIEnv('Content_Length') PostData = params if datatype(ln, 'W') then do while length(PostData) < ln r.0 = 1; r.1 = sk; Rc = SockSelect('r.',,, 5) if Rc < 0 then do say 'err='errno 'h='h_errno leave end if Rc > 0 & r.0 > 0 & r.1 = sk then do Rc = SockRecv(sk, 'txt', 2000) PostData = PostData''txt call charout , Rc end end 〜 |
では, 次に出力側。一般的な CGIとは異なり, SilkWebでは CGIプログラムの出力は queueで行います。
このため出力に先だって, 内容を組み立てておかなくてはなりません。
また, この時 応答ヘッダーを指定する事ができます。queue <応答ヘッダー>; queue <結果>;
の順番で指定します。指定する順番を逆にしたい場合は pushを使います。
クライアントから要求があったものを送り返す時に, サーバーは次のものを返します。
Server: SilkWeb(RxHTTPd)/1.2 Date: Sun, 22 Feb 1998 18:30:20 JST Content-type: text/html Content-length: 12345 Last-Modified: Sun, 06 Nov 1994 08:49:37 GMT ※ これは適当に作成したものなので, 実在のものとは関係ありません。 |
上の図の中に, 最終更新日付とファイルサイズが含まれています。 Webブラウザを使って同じ画面を複数回見る時に, 2度目以降はブラウザのキャッシュが使われる場合がありますが, その判断基準となっている情報です (送り出す判断を行うのはサーバーです)。 また, Web siteの更新チェックプログラムも, 大抵これを利用しています。
通常, これらはサーバーが生成するものですが, それを変更したい場合があります。
たとえば SSIの場合, 最終更新日とは その日, その時間になってしまい,
オリジナルファイルの更新日付とは違ったものになります。(CGIも同様ですが, オリジナルファイルという意味で多少異なります (^^;)
他に, クッキー(Cookie:
, Set-Cookie
)を返す事にも関係があります。
これらをブラウザに返すには, HTMLファイルの headタグの間にそれらを指定します。
<html><head> <meta http-equiv="Last-Modified" content="Sun, 06 Nov 1994 08:49:37 GMT"> <meta http-equiv="Set-Cookie" content="listcount=5; expires=Sat, 01 Jan 2000 00:00:00 GMT;"> 〜 |
しかし, この記述を行ってもブラウザが認識してくれるとは限りません。
つまり, HTMLには メタ情報を埋め込むための拡張機能があるが, それがどのように扱われるかは
サーバー, およびクライアント(Webブラウザ)次第ということです。(RFC1866J より)
(N.N. は, クッキーは認識しました。他は試していません (^^;)
この SilkWebサーバーでは, SSIに限り HTMLファイルからメタ情報を取り出し, 応答ヘッダーとして返す事ができます。
ですが, デフォルトではその機能は働かないようにしています。
(つまり, いまのところブラウザ任せになっています)
クライアントからの要求パス[5]を,
サーバーの実際のパスへ割り当てるために, 割り当て定義ファイルが用いられます。
このファイルは, このほか各種の機能の割り当てにも使われます。
このファイルも 構成ファイル同様(書式は違う)
テキストファイルなのでエディターで編集できます。
が, 専用の編集プログラムも付属していますので通常はそちらを使った方が編集が楽でしょう。
通常, ファイル名は SilkWeb.map。このファイル名は, 構成ファイル(SilkWeb.cnf)によって指定します。
以下, この割り当て定義ファイルの事を mapファイルとします。
mapファイルは構成ファイルと異なり, SilkWeb サーバー稼働中でも編集が可能。
設定を変更した場合でも, 再立ち上げの必要はありません。(自動ローディングされる)
指定された内容は, クライアントからの要求があった時に, 先頭から順に一行ずつスキャンされ,
該当する行が見つかった時点でスキャンは終了し その行の定義によって処理が行われます。
ただし, その行に機能が指定されていなかった場合, スキャンは続行。この時, 要求パスはその指定により割り当てが変更されます。
mapファイルの行の形式は, 次の通り。
'テンプレート' 機能 '割り当てパス' [サーバーのIPアドレス]行頭の文字が, 各項目を分けるデリミタにもなっているため, 各項目を " や / などで区切る事もできます。 ただし # や ; はコメントとして用いるので, これに使う事はできません。
それでは, 各項目を順に説明します。
Mapは 通常のページの場合に指定します。
Redirectは 別のページへ, あるいは別のホストへ飛びます。割り当てパスには飛び先を指定。
Failはアクセス禁止の指定です。クライアントにはファイルが存在しないように見えます。
割り当てパスは指定しない。
Execは これが CGIであることを指定します。
SSiは SSIの指定です。
Listdirは ディレクトリの一覧表示可能の指定。ただし表示を行うモジュールがサーバーに必要。
Authorizeは 認証を行う事を指定。機能名と同時に regionを指定する。これは ()でくくる。
(指定なし) 次の定義行へスキップ(パス変更は行われる)
とても複雑そうですが, 例を見るとそうでもないと思います。
テンプレート | 割り当てパス | 説明 |
---|---|---|
/cgi-bin/*.cgi | /cgi-bin/*.cmd | 拡張子の変換 |
/cgi-bin/* | /cgi-bin/*.cmd | 拡張子の補完 |
/admin/icon/*.htm | *.html | 前の部分省略, '/admin〜' とみなす |
/secret/*.txt | /html/secret/ | 後の部分省略, 最後が '/'なら '/*.txt'とみなす |
/secret/*.txt | /html/secret/* | これは, 拡張子を取り除く事になる |
/secret/ | /html/secret/ | ... |
/html/ | /html/Index.htm | ... |
/html/* | /html/Readme | すべてをここへ集める |
/html/ | /html/*.htm | /html/.htm ... 意味なし |
以上が mapファイルの行です。
さらに, 要求パスが いずれかの行にヒットして, それが変更された後, 条件によっては処理が加えられます。
それは 構成ファイルの WPageセクションの部分で,
SilkWeb サーバーは, 構成ファイル(SilkWeb.cnf)を書替えることで, ある程度 動作を変更させる事ができます。
このファイルは 単純なテキストファイルですのでエディターなどで
編集できます。(専用の編集プログラムも付属していますので使いやすい方を選択して下さい)
構成ファイルには 現在 3つのセクションがあります。
- HTTP
- … プロトコルに関する部分
- JLog
- … アクセス記録に関する部分
- WPage
- … Web pageの指定に関する部分
まずは HTTPセクションから。HTTPセクションには 次のような項目があります。
SelWtTimeは, select() のタイムアウトの引数に指定する値。 (送)受信の最大待ち時間というようなもの。単位は秒数。 長くても大丈夫です。5分(=300) とか 一時間(=3600)とかでも構いません。長い方がシステムに負担を掛けないはずです。
MaxRecvLn。これは recv() の引数の長さの指定。最大受信長さ。 1500〜2000 くらいのが指定されていれば変更する必要はないでしょう。
MaxSendLnは, 内部で使う値です。 クライアントからの要求を並行で対応するために, 送り出す情報の長さを制限するもの。
Portは, このサーバーが待ち受けるポート番号。 HTTPでは 80です。
次に JLogセクション。ここには次のような項目があります。
LogLmtはアクセス記録の限界サイズ。この値を超えた場合, アクセス記録は 次の世代のファイルに変更されます。
LogMaxはアクセス記録のバックアップの数。世代数(?)
最後は WPageセクション。ここには次のような項目があります。
WelPageはwelcome page のファイル名。 URLにパス名だけを指定した場合, サーバーがファイル名を補完することになりますが, この時のファイル名です。
MapFileは割り当て定義ファイルのファイル名。 このセクションには関係がないような項目 (^^;
この 構成ファイル(SilkWeb.cnf)は, 起動時に一度読み込まれるだけなので, 修正を行った場合 いったん Web server を止め, 再起動の必要があります。
RxSock 外部関数パッケージには, ある重大な問題があります。
といっても, システムをダウンさせたりするものではありません。
このパッケージを使用したプログラムが, それを起動したコマンド窓もろとも落ちてしまう, というものです。
この現象は, RxSockによって一度に複数のソケットを使っている状態で発生するようです。
もちろん SilkWebも例外ではなく, 複数のブラウザ(というかクライアント)から
同時にアクセスがあると異常終了する事があります。
これを防ぐには, Hobbesの RxSock を使うという手段があります。〆(^^) の所では 今のところ問題は起きていないようです。 ただし, こちらは OS/2標準のものと比べ, 一部関数が足りないようです。 判っている範囲では次のようなものです。
追記
Warp ver 4.5なら大丈夫かも知れません。今のとこ正常に動いています。
SSI は Webブラウザから要求を受けたサーバーが, ファイルを送り出す時点で, 内容を書替えながら送り出す機能です。 SilkWeb でのそれは 割り当て定義ファイルで, SSI の指定があると機能します。 その指定された HTMLファイルは, ブラウザから要求された時に, 通常とは異なる方法で送り出される事になります。
SSIとして扱う HTMLファイルは, 内容も通常のものと微妙に異なります。 SSI対応ファイルを 通常のHTMLファイルのように割り当てると, 少し変な内容がブラウザに表示される事になります。 また, 通常の HTMLファイルを SSIに割り当ててもあまりメリットはありません。
SSI対応ファイルには SSIコマンドを記述できます。 SSIコマンドは "{" と "}" で囲んで指定します。 この SSIコマンドには次のようなものがあります。
{#〜} | "#" で始まる場合はコメント (文字列は組み込まれない) |
---|---|
{!〜} | "!" で始まる場合, それを実行 (文字列は組み込まれない) |
{include FILE} | FILE を組み込む |
{?VAR} | 変数VAR を組み込む (extract(VAR)と同じ) |
{loop VAR} | ループ開始 (変数VAR に指定された回数繰り返す) |
{end} | ループの終わり |
{FUNC()} | 関数 FUNC を実行し, 結果の文字列を組み込む |
例: [1]
<html><head><title>{?CURFILE}</title></head> {!vn = '□'; v.vn = '<p><hr size=7 width=7>';} <body><h1>ちょっとした SSI</h1> {?□}{#←ここに 上で定義した <hr>〜 が組込まれる} {!parse value date('o') with yy'/'mm'/'dd;} <p>今日は {StdFullDate(yy, mm, dd)} です。{date('w')} です。 〜 |
"関数"には Rexx の標準の関数や, ほかに次のような関数を指定できます。
extract(VAR) | 変数VAR を展開する |
---|---|
if(BOOL, TRUE, FALSE) | BOOL が真の場合は TRUE側を展開, BOOLが偽の場合は FALSE側を展開する。 |
FileDate(FILE) | ファイル"FILE" の更新日時を展開する。 引数がなかった場合は 処理中の SSI対応ファイルの更新日時を展開する。[2] |
StdFullDate(Y,M,D) | 年Y, 月M, 日D を指定し Internet の日付フォーマットに変換する。[3] |
ChangeStr(...) | 同名の Object REXXの関数と同じ |
変数の中には, 最初から使われている変数(予約変数)があります。 次の変数です。
<title>{?CURFILE}</title>
指定します (大文字で指定して下さい)。
- [1]
- {?VAR} での変数の展開について … 展開される変数は, 直接の Rexxの変数ではありません。 stem vの tailとして扱っています。
- [2]
- FileDate() では タイムゾーンは "GMT" になります。 しかし変換されている訳ではなく, タイムゾーンの項目が "GMT"となっているだけです。
- [3]
- StdFullDate() では 時刻やタイムゾーンの項目はありません。
- [4]
- "JST"にしていないのは, ブラウザからの要求時に "JST"→"GMT" のように変換されて要求されるためです。
- [5]
- 代表的なものは, http://ホスト名 の後に続く /で始まる一連の文字列