Apache Module

13,453 views
13,150 views

Published on

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,453
On SlideShare
0
From Embeds
0
Number of Embeds
974
Actions
Shares
0
Downloads
101
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

Apache Module

  1. 1. Apache モジュール入門 ( 株 ) ライブドア 池邉智洋
  2. 2. Apache モジュールとは? <ul><li>Apache Web サーバの機能を追加、削除する仕組み </li></ul><ul><li>標準で使われている多くの機能もモジュール として実装されている </li></ul><ul><li>最低限必要な機能は Apache Core, Apache API として実装 </li></ul>
  3. 3. Apache の構造 Apache Core Apache API Apache モジュール
  4. 4. Apache モジュールの利点、欠点 <ul><li>利点 </li></ul><ul><ul><li>C 言語で記述するため高速 </li></ul></ul><ul><ul><li>Web サーバと一体化した処理のため一般の Web アプリケーションでは難しい処理も可能 </li></ul></ul><ul><li>欠点 </li></ul><ul><ul><li>コンパイルが必要 </li></ul></ul><ul><ul><li>デバッグが困難 </li></ul></ul><ul><ul><li>フォームがあるような一般的な Web アプリケーションにはあまり向かない </li></ul></ul>
  5. 5. 使用箇所 <ul><li>大量のリクエストを高速に処理 </li></ul><ul><ul><li>カウンターモジュール </li></ul></ul><ul><ul><li>ア クセス解析ログ取得 </li></ul></ul><ul><li>構築後の変更が少ない箇所 </li></ul><ul><ul><li>ポータルトップページ </li></ul></ul><ul><li>Apache モジュールならではの処理 </li></ul><ul><ul><li>カスタム URI => ストレージマッピング </li></ul></ul><ul><ul><li>特殊な認証 </li></ul></ul>
  6. 6. Apache のライフサイクル <ul><li>Apache のリクエストサイクルの代表的なフェーズ </li></ul><ul><li>左図の任意のフェーズにフック関数を登録して実行 </li></ul>クライアントの接続 リクエスト読み込み URI 変換 アクセス制御 認証 微調整 (fixup) コンテンツ出力 ロギング インプットフィルタ アウトプットフィルタ
  7. 7. APR <ul><li>Apache Portable Runtime - http://apr.apache.org </li></ul><ul><li>C 言語における移植性 (Portability) の確保を行なってくれる抽象レイヤー </li></ul><ul><li>関数名は apr_ から始まる </li></ul><ul><li>メモリプールの管理 </li></ul><ul><li>文字列操作 </li></ul><ul><li>複雑なデータ構造 ( 動的配列、コンテナ型 ) </li></ul><ul><li>ファイル I/O </li></ul><ul><li>etc… </li></ul>
  8. 8. メモリ管理 <ul><li>apr_pool_t * </li></ul><ul><li>領域の確保を行なう (malloc 相当 ) </li></ul><ul><li>確保した領域について明示的な free は不要 </li></ul>my_module_conf *conf = apr_palloc(p,sizeof(my_module_conf)); 領域の確保
  9. 9. 文字列操作 <ul><li>C 言語では複雑になりがちな文字列操作を簡単に </li></ul><ul><li>返り値の領域はメモリプールから確保される </li></ul>char *str = apr_pstrdup(p, src); 文字列のコピー char *str = apr_pstrcat(p, str1, str2, NULL); 文字列の連結 char *str = apr_psprintf(p, “%d ”, n); 文字列フォーマット
  10. 10. 動的配列 <ul><li>apr_array_header_t * </li></ul><ul><li>動的に拡張される配列 </li></ul>apr_array_header_t *arr = apr_array_make(p, 10, sizeof(char *)); 配列の生成 *(const char **)apr_array_push(arr) = val; 値の追加 arr->nelts; 要素数 char **elts = arr->elts; 配列実体
  11. 11. テーブル <ul><li>apr_table_t * </li></ul><ul><li>HTTP ヘッダの処理等に使用される key => value コンテナ </li></ul><ul><li>動的に拡張される </li></ul>apr_table_t *tbl= apr_table_make(p, 12); テーブルの作成 apr_table_set(tbl, key, val); 値のセット char *val = apr_table_get(tbl, key); 値の取得 apr_table_unset(tbl, key); 値の削除
  12. 12. apxs <ul><li>apxs = APache eXtenSion tool </li></ul><ul><li>Apache のモジュール作成、コンパイル等を支援するツール </li></ul>% apxs –g –n <module_name> 雛形の作成 # apxs –i –a -c mod_<module_name>.c コンパイルしてインストール
  13. 13. 雛形の作成 % apxs -g -n hello Creating [DIR] hello Creating [FILE] hello/Makefile Creating [FILE] hello/modules.mk Creating [FILE] hello/mod_hello.c Creating [FILE] hello/.deps # cd hello/ # apxs –i –a –c mod_hello.c # /usr/local/apache2/bin/apachectl stop # /usr/local/apache2/bin/apachectl start <Location /hello> SetHandler hello </Location> httpd.conf
  14. 14. 確認
  15. 15. ソースコード 1 #include &quot;httpd.h&quot; #include &quot;http_config.h&quot; #include &quot;http_protocol.h&quot; #include &quot;ap_config.h&quot; /* コンテントハンドラ */ static int hello_handler(request_rec *r) { if (strcmp(r->handler, &quot;hello&quot;)) { return DECLINED; } r->content_type = &quot;text/html&quot;; if (!r->header_only) ap_rputs(&quot;The sample page from mod_hello.c &quot;, r); return OK; }
  16. 16. request_rec 構造体 <ul><li>HTTP リクエストを表現した構造体 </li></ul><ul><li>include/httpd.h で定義 </li></ul><ul><li>モジュールを書く上で最もよく使う構造体 </li></ul><ul><ul><li>r->handler 処理するハンドラの名称 </li></ul></ul><ul><ul><li>r->content_type Content-Type ヘッダ </li></ul></ul><ul><ul><li>r->header_only HEAD リクエストかどうか </li></ul></ul>
  17. 17. request_rec 構造体 <ul><li>代表的なメンバ </li></ul><ul><ul><li>r->pool リクエスト毎のメモリプール </li></ul></ul><ul><ul><li>r->args QUERY_STRING 値 </li></ul></ul><ul><ul><li>r->method_number リクエストメソッドの数値表現 </li></ul></ul><ul><ul><li>r->headers_in リクエストヘッダ apr_table_t 型 </li></ul></ul><ul><ul><li>r->headers_out レスポンスヘッダ apr_table_t 型 </li></ul></ul><ul><ul><li>r->uri URI </li></ul></ul><ul><ul><li>r->filename DISK 上のファイル名 </li></ul></ul>
  18. 18. Apache API <ul><li>Apache から提供される API </li></ul><ul><li>ap_ から始まる関数群 </li></ul><ul><li>コンテンツの出力 </li></ul><ul><ul><li>ap_rputs(const char *str, requst_rec *r) </li></ul></ul><ul><ul><li>ap_rwrite(const void *buf, int nbytes, requst_rec *r) </li></ul></ul><ul><ul><li>ap_rprintf(request_rec *r, const char *fmt, …); </li></ul></ul>
  19. 19. ハンドラの返り値 <ul><li>OK - 処理成功 </li></ul><ul><li>DECLINED – 次のモジュールに処理を任せる </li></ul><ul><li>HTTP_* </li></ul><ul><ul><li>HTTP_NOT_FOUND </li></ul></ul><ul><ul><li>HTTP_FORBIDDEN </li></ul></ul><ul><ul><li>HTTP_INTERNAL_SERVER_ERROR </li></ul></ul><ul><ul><li>etc… </li></ul></ul>
  20. 20. モジュールの連鎖 <ul><li>Chain of Responsibility 的 </li></ul><ul><li>DECLINED が返された場合、次のモジュールが処理を行なう </li></ul>mod_foo foo_handler() mod_bar bar_handler() default default_handler()
  21. 21. ソースコード 2 static void hello_register_hooks(apr_pool_t *p) { ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA hello_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config */ NULL, /* merge per-dir config */ NULL, /* create per-server config */ NULL, /* merge per-server config */ NULL, /* config file commands */ hello_register_hooks /* register hooks */ };
  22. 22. ハンドラの登録 <ul><li>ap_hook_handler コンテントハンドラを登録 </li></ul><ul><li>フェーズ毎に ap_hook_* 関数が存在 </li></ul><ul><ul><li>ap_hook_translate_name </li></ul></ul><ul><ul><li>ap_hook_access_checker </li></ul></ul><ul><ul><li>ap_hook_fixups </li></ul></ul><ul><ul><li>ap_hook_log_transaction </li></ul></ul><ul><ul><li>etc… </li></ul></ul>
  23. 23. モジュールの定義 <ul><li>モジュールを定義する構造体 </li></ul><ul><ul><li>ディレクトリ毎の設定の初期化 </li></ul></ul><ul><ul><li>ディレクトリ毎の設定のマージ </li></ul></ul><ul><ul><li>サーバ毎の設定の作成 </li></ul></ul><ul><ul><li>サーバ毎の設定のマージ </li></ul></ul><ul><ul><li>設定値のリスト </li></ul></ul><ul><ul><li>フックの登録 </li></ul></ul>
  24. 24. 設定値の使用 <ul><li>mod_hello を設定ファイルに指定された文字列を出力するように変更 </li></ul><Location /hello> SetHandler hello HelloMessage “Hello livedoor!” </Location> httpd.conf
  25. 25. 設定値を格納する構造体 typedef struct { char *msg; } hello_cfg; 構造体の宣言 static void *create_hello_cfg(apr_pool_t *p, char *dir) { hello_cfg *cfg = apr_palloc(p, sizeof(hello_cfg)); cfg->msg = &quot;Hello World!&quot;; return (void *)cfg; } 初期化
  26. 26. ディレクティブの定義 static const char *cmd_set_message(cmd_parms *cmd, void *c, const char *v) { hello_cfg *cfg = (hello_cfg *)c; cfg->msg = apr_pstrdup(cmd->pool, v); return NULL; } static const command_rec hello_cmds[] = { AP_INIT_TAKE1(&quot;HelloMessage&quot;, cmd_set_message, NULL, ACCESS_CONF, &quot;Set mod_hello message.&quot;), {NULL} }; HelloMessage ディレクティブを定義
  27. 27. ディレクティブ名の登録 <ul><li>AP_INIT_NO_ARGS </li></ul><ul><li>AP_INIT_TAKE1 </li></ul><ul><li>AP_INIT_TAKE2 </li></ul><ul><li>AP_INIT_TAKE12 </li></ul><ul><li>AP_INIT_ITERATE </li></ul><ul><li>AP_INIT_FLAG </li></ul><ul><li>AP_INIT_RAW_ARGS </li></ul><ul><li>etc… </li></ul>
  28. 28. ディレクティブの設定場所 <ul><li>OR_LIMIT </li></ul><ul><li>OR_OPTIONS </li></ul><ul><li>OR_FILEINFO </li></ul><ul><li>OR_AUTHCFG </li></ul><ul><li>OR_INDEXES </li></ul><ul><li>OR_ALL </li></ul><ul><li>ACCESS_CONF </li></ul><ul><li>RSRC_CONF </li></ul>
  29. 29. モジュールに登録 module AP_MODULE_DECLARE_DATA hello_module = { STANDARD20_MODULE_STUFF, hello_create_cfg, NULL, NULL, NULL, hello_cmds, hello_register_hooks }; モジュール定義を変更
  30. 30. 設定値の利用 static int hello_handler(request_rec *r) { hello_cfg *cfg = ap_get_module_config(r->per_dir_config, &hello_module); if (strcmp(r->handler, &quot;hello&quot;)) { return DECLINED; } r->content_type = &quot;text/html&quot;; if (!r->header_only) ap_rprintf(r, &quot;%s &quot;, cfg->msg); return OK; } ap_get_module_config で設定値を参照
  31. 31. さらに複雑なモジュールを書くために <ul><li>modules ディレクトリ以下はよいお手本 </li></ul><ul><li>http://apr.apache.org/ </li></ul><ul><li>http://httpd.apache.org/docs/2.2/developer/ </li></ul><ul><li>http://modules.apache.org/ </li></ul>
  32. 32. おしまい

×