Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Apache モジュール入門 ( 株 ) ライブドア 池邉智洋
Apache モジュールとは? <ul><li>Apache Web サーバの機能を追加、削除する仕組み </li></ul><ul><li>標準で使われている多くの機能もモジュール として実装されている </li></ul><ul><li>最...
Apache の構造 Apache Core Apache API Apache モジュール
Apache モジュールの利点、欠点 <ul><li>利点 </li></ul><ul><ul><li>C 言語で記述するため高速 </li></ul></ul><ul><ul><li>Web サーバと一体化した処理のため一般の  Web  ア...
使用箇所 <ul><li>大量のリクエストを高速に処理 </li></ul><ul><ul><li>カウンターモジュール </li></ul></ul><ul><ul><li>ア クセス解析ログ取得 </li></ul></ul><ul><li...
Apache のライフサイクル <ul><li>Apache のリクエストサイクルの代表的なフェーズ </li></ul><ul><li>左図の任意のフェーズにフック関数を登録して実行 </li></ul>クライアントの接続 リクエスト読み込み...
APR <ul><li>Apache Portable Runtime - http://apr.apache.org </li></ul><ul><li>C 言語における移植性 (Portability) の確保を行なってくれる抽象レイヤー ...
メモリ管理 <ul><li>apr_pool_t * </li></ul><ul><li>領域の確保を行なう (malloc  相当 ) </li></ul><ul><li>確保した領域について明示的な  free  は不要 </li></ul...
文字列操作 <ul><li>C 言語では複雑になりがちな文字列操作を簡単に </li></ul><ul><li>返り値の領域はメモリプールから確保される </li></ul>char *str = apr_pstrdup(p, src); 文字...
動的配列 <ul><li>apr_array_header_t * </li></ul><ul><li>動的に拡張される配列 </li></ul>apr_array_header_t *arr =  apr_array_make(p, 10, ...
テーブル <ul><li>apr_table_t * </li></ul><ul><li>HTTP ヘッダの処理等に使用される  key => value  コンテナ </li></ul><ul><li>動的に拡張される </li></ul>a...
apxs <ul><li>apxs = APache eXtenSion tool </li></ul><ul><li>Apache のモジュール作成、コンパイル等を支援するツール </li></ul>% apxs –g –n <module_...
雛形の作成 % apxs -g -n hello Creating [DIR]  hello Creating [FILE] hello/Makefile Creating [FILE] hello/modules.mk Creating [F...
確認
ソースコード 1 #include &quot;httpd.h&quot; #include &quot;http_config.h&quot; #include &quot;http_protocol.h&quot; #include &qu...
request_rec  構造体 <ul><li>HTTP リクエストを表現した構造体 </li></ul><ul><li>include/httpd.h  で定義 </li></ul><ul><li>モジュールを書く上で最もよく使う構造体 <...
request_rec  構造体 <ul><li>代表的なメンバ </li></ul><ul><ul><li>r->pool  リクエスト毎のメモリプール </li></ul></ul><ul><ul><li>r->args QUERY_STR...
Apache API <ul><li>Apache  から提供される  API </li></ul><ul><li>ap_  から始まる関数群 </li></ul><ul><li>コンテンツの出力 </li></ul><ul><ul><li>a...
ハンドラの返り値 <ul><li>OK  -  処理成功 </li></ul><ul><li>DECLINED –  次のモジュールに処理を任せる </li></ul><ul><li>HTTP_* </li></ul><ul><ul><li>H...
モジュールの連鎖 <ul><li>Chain of Responsibility  的 </li></ul><ul><li>DECLINED  が返された場合、次のモジュールが処理を行なう </li></ul>mod_foo foo_handl...
ソースコード 2 static void hello_register_hooks(apr_pool_t *p) { ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE); } ...
ハンドラの登録 <ul><li>ap_hook_handler    コンテントハンドラを登録 </li></ul><ul><li>フェーズ毎に  ap_hook_*  関数が存在 </li></ul><ul><ul><li>ap_hook_t...
モジュールの定義 <ul><li>モジュールを定義する構造体 </li></ul><ul><ul><li>ディレクトリ毎の設定の初期化 </li></ul></ul><ul><ul><li>ディレクトリ毎の設定のマージ </li></ul></...
設定値の使用 <ul><li>mod_hello  を設定ファイルに指定された文字列を出力するように変更 </li></ul><Location /hello> SetHandler hello HelloMessage “Hello live...
設定値を格納する構造体 typedef struct { char *msg; } hello_cfg; 構造体の宣言 static void *create_hello_cfg(apr_pool_t *p, char *dir) { hell...
ディレクティブの定義 static const char *cmd_set_message(cmd_parms *cmd, void *c, const char *v) { hello_cfg *cfg = (hello_cfg *)c; c...
ディレクティブ名の登録 <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_I...
ディレクティブの設定場所 <ul><li>OR_LIMIT </li></ul><ul><li>OR_OPTIONS </li></ul><ul><li>OR_FILEINFO </li></ul><ul><li>OR_AUTHCFG </li...
モジュールに登録 module AP_MODULE_DECLARE_DATA hello_module = { STANDARD20_MODULE_STUFF,  hello_create_cfg,  NULL,  NULL,  NULL,  ...
設定値の利用 static int hello_handler(request_rec *r) { hello_cfg *cfg =  ap_get_module_config(r->per_dir_config, &hello_module)...
さらに複雑なモジュールを書くために <ul><li>modules  ディレクトリ以下はよいお手本 </li></ul><ul><li>http://apr.apache.org/ </li></ul><ul><li>http://httpd....
おしまい
Upcoming SlideShare
Loading in …5
×

Apache Module

14,815 views

Published on

Published in: Technology
  • Be the first to comment

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. おしまい

×