試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

libsoupライブラリのHTTPサーバ機能を用いたテスト(メモ)

GNU/Linuxにはlibsoupというネットワーク関係のライブラリがあるのだが、これはGObjectライブラリに基づいており、GTK+,libnotify,GStreamerなどと同様に、Vala言語からはそのまま言語の文法上でライブラリの機能を(オブジェクト指向で)扱うことができる。
この中にはHTTPサーバ機能が存在し、Webブラウザからアクセスしたときに色々なデータを返すようにでき、単純にファイルの内容を開いてそれを返すだけでなく、プログラムの一部としてWebページ形式のインターフェース(Webブラウザでアクセスして操作する形)を提供することもできるようになる。
もちろん、Vala言語ではHTTPサーバ機能を提供するクラスを継承して処理を記述するということも簡単にできる。

libsoupのAPIなどに関するメモ

  • バージョンは2.2系と2.4系があるのだが、2.4系ではValaの言語バインディングlibsoup-2.4.vapiを用いることになるため、valacには「--pkg libsoup-2.4」オプションを付ける(別途libsoupの開発パッケージも必要)・もちろんコンパイルしたものは開発パッケージなしで動作する
  • Soup.ServerというクラスがHTTPサーバの機能を提供し、継承して使うこともできる
  • Soup.Serverクラスを継承する場合、待ち受けるTCP/IPのポート番号(プロパティport)はコンストラクタ内でGLib.Object()を呼び出して指定する*1(継承しない場合はコンストラクタ引数を用いて「new Soup.Server (Soup.SERVER_PORT, [ポート番号])」のように生成する)
  • Soup.Serverオブジェクトを作成したらメンバ関数run()を呼ぶことで待ち受けのループに入って(別のところで)quit()が呼ばれるまで先には進まないが、非同期版のrun_async()もあり、呼び出し直後に先の処理に進む(GLibやGTK+のメインループを用いる場合などに便利)
  • サーバの応答はリクエストURLに応じて変えることができ、パスの先頭からの文字列とハンドラをSoup.Serverオブジェクトのadd_handler()に指定することでパスとハンドラを関連付ける・add_handler()で「/foo」のパスを指定すると「/foo」の他「/foobar」などのURLを呼び出したときにもそのハンドラが呼ばれる
  • ハンドラの引数はServerCallbackのもの(Soup.Server server, Soup.Message msg, string path, GLib.HashTable query, Soup.ClientContext client)となる
  • ハンドラの4番目の引数(query)はURLの後ろに「?[名前1]=[値1](&[名前2]=[値2]&[名前3]=[値3]...)」のようなキー文字列と値のペアの部分が付いた場合(GETメソッド使用時)にそれがGLib.HashTableオブジェクトとして入ったもの(URLの解析から格納まではlibsoupライブラリが既に処理している)で、「?」の後ろの部分がなければnullになる
  • GLib.HashTable型はキーとそれに対応する値をペアで格納するオブジェクトで詳しくは「GLibのハッシュテーブルをVala言語で用いる(前半)」「GLibのハッシュテーブルをVala言語で用いる(後半)」を参照
  • ハンドラの引数pathはリクエストのパスを示す(「/foo」のURLを呼び出すとpathは「/foo」となる)
  • ハンドラでは引数msgのメンバ関数set_response()msg.set_status()を呼んでWebブラウザなどのHTTPクライアントに渡す結果を設定する
  • set_response()では応答の種類(content type)やデータ本体などを渡し、msg.set_status()はHTTPサーバがWebブラウザなどのクライアントへ返すコードをSoup.KnownStatusCodeとして返す

Webブラウザから見たときの動作

一部の内容は上のメモとかぶるが、上記のHTTPサーバ機能を用いたプログラムを起動後Webブラウザ
http://127.0.0.1:[プログラム内で指定したポート番号]/
にアクセスするとサーバオブジェクト(Soup.Serverクラス)のadd_handler()で「/」のパスに指定したハンドラが呼ばれてその中の2番目の引数(Soup.Messageオブジェクト)のset_status()で「Soup.KnownStatusCode.OK」を引数に指定したときにset_response()で設定したデータ(HTMLのソースなど)がサーバから得られ、HTML文書の場合はその内容が整形されてWebブラウザに表示される。

Webページというユーザインターフェース

冒頭でも少し書いているが、libsoupのHTTPサーバ機能は、ハンドラの書き方によっては「何か操作を実行したときにそれに対応する処理を呼ぶ」形の、「Webページというグラフィカルインターフェースを持つプログラム」を作るのに使える。
一般的に、GUIアプリケーションはユーザインターフェースの部品(ウィジェット)の操作があるとそれに対応した処理を呼び出すようになっているが、libsoupのHTTPサーバ機能を用いたプログラムでもWebブラウザからのHTTPリクエストというイベントがあったときにその詳細な内容によって適切な処理を行いつつその処理内容に合ったHTMLソースを(動的に)出力するという形をとることになり、ユーザから見たときにGUIアプリケーションに近い振舞いをするようにできる(もちろん、HTMLやCSSについてのある程度の理解は必要)。
具体的にはアクセスするページのパスとハンドラ4番目の引数(クエリ)によって挙動が変わるようにコードを記述することになる。

(「libsoupライブラリのHTTPサーバ機能を用いたテスト(例)」に続く)

関連記事:

使用したバージョン:

  • libsoup-2.4 2.30.2
  • Vala 0.10.1

*1:プロパティportは「{ get; construct; }」となっており、オブジェクト生成時にしか代入はできず、その代入を行うのがGLib.Object()となる