スポンサーサイト

一定期間更新がないため広告を表示しています

  • 2010.02.10 Wednesday
  • -
  • -
  • -
  • -
  • by スポンサードリンク

apache拡張モジュール 開発日記12 〜SetCookie発行〜

モジュールでSetCookieを発行する方法を載せます。
なにやらPerlやらCGIやらで発行しているのはよく見るんですが
C言語でやる方法がすぐ見つからなかったので、自分で記事を作ります

apr_table_set(r->headers_out, "Set-Cookie", "クッキー設定のための文字列");

これで正常レスポンスを返す場合に、クッキー設定のための文字列を使って
SetCookieを発行します。
ちなみに、エラーレスポンスを返す時は、これじゃSetCookieされません。
apr_table_set(r->err_headers_out, "Set-Cookie", "クッキー設定のための文字列");
これでエラーの場合にSetCookieを発行できます。


クッキー設定のための文字列って何ですか?
まず、SetCookieの根本的な使い方を知る必要があります。
こちらを見てもらうとわかると思うんですが、

Set-Cookie: NAME=tanaka; Tue, 31-Dec-2030 23:59:59;

っていう感じにHTTPヘッダを発行するんですが、

Set-Cookie: NAME=tanaka; Tue, 31-Dec-2030 23:59:59;
上の赤い部分の文字列を、apr_table_setの第三引数に渡すと
Apacheが、このtableを読み込んで発行してくれます。

簡単ですねー


apache拡張モジュール 開発日記11 〜REDIRECT〜

apacheのモジュール内でリダイレクトの処理を載せますねー。

apr_table_set(r->headers_out, "Location", "/Login.html");
return REDIRECT;

これで第三引数のURIに移動できるっつーわけです。

このAPRはなんなのかというと
内部テーブルに key=valueの形式で値を保持しておくものです。

レスポンスのHTTPヘッダーを司る場所(r->headers_out)の、
URIを指定するためのkey値(location)に対するvalueに、
"Login.html"とセットしています。

レスポンスを作るときにこの値を見て生成しているので
無事にRedirectされるんじゃなかろうか。

ちなみに私の環境ではreturn REDIRECTできなかったから
return 302;にしました。
何かincludeする必要があるのかな・・・。

apache拡張モジュール 開発日記10 〜SetHandler〜

Httpd.confに記述する
<Location></Locatin>や<Directory></Directory>の間に書く
SetHandlerの意味がやっとわかった。

開発日記2で作った、test.cの例で説明すると、
<Location "/test/">
  SetHandler test
</Location>
って書くって説明してたんだけど、SetHandler testって
何気なく書いてた部分は、test.cの名前から来てるんじゃなくて自分で勝手に決めれる名前だった。

どういうことかっていうと、
http://localhost/test/にアクセスした時に、自分で勝手に決めたHandlerが処理される記述になる。
開発日記では作ったモジュールのソースに
if(strcmp(r->handler, "test")) {
   return DECLINED;
}
上のような記述があって、このモジュールを処理するHandlerを決めてるんだわ。
このif文が無くなると、どんなHandlerでも処理しちゃうのよ。
っていうか、Handlerがなくても処理しちゃうわ。
具体的にいうと、http://localhost/これ以降適当な文字
にアクセスしても、このモジュールが処理されちゃう。

今までの勘違いから、LocationやDirectoryの中に
SetHandlerが2つ書けないからモジュール一個しか使えないもんだと勘違いしてたんだけど
2つのモジュールで
if(strcmp(r->handler, "test")) {
   return DECLINED;
}
ってかましてやれば、2つ処理するやん!
しかも処理の順を決めれるやん!

よし、理解

apache拡張モジュール 開発日記9 〜request_rec 構造体〜

・HTTPリクエストを表現した構造体
・include/httpd.hで定義
・モジュールを書く上で最もよく使う構造体

r->handler 処理するハンドラの名称
r->content_type Content-Typeヘッダ取得
r->header_only HEADリクエストかどうか
r->pool リクエスト毎のメモリプール
r->args QUERY_STRING値
r->method_number リクエストメソッドの数値表現?
r->headers_in リクエストヘッダ apr_table_t型
r->headers_out レスポンスヘッダ apr_table_t型
r->r->uri URI
r->filename DISK上のファイル名

そのうち綺麗に書き直す

apache拡張モジュール 開発日記8 〜MOJULEからreturnの型すべて〜

httpd.hに載ってたので全て記載

#define HTTP_CONTINUE 100
#define HTTP_SWITCHING_PROTOCOLS 101
#define HTTP_PROCESSING 102
#define HTTP_OK 200
#define HTTP_CREATED 201
#define HTTP_ACCEPTED 202
#define HTTP_NON_AUTHORITATIVE 203
#define HTTP_NO_CONTENT 204
#define HTTP_RESET_CONTENT 205
#define HTTP_PARTIAL_CONTENT 206
#define HTTP_MULTI_STATUS 207
#define HTTP_MULTIPLE_CHOICES 300
#define HTTP_MOVED_PERMANENTLY 301
#define HTTP_MOVED_TEMPORARILY 302
#define HTTP_SEE_OTHER 303
#define HTTP_NOT_MODIFIED 304
#define HTTP_USE_PROXY 305
#define HTTP_TEMPORARY_REDIRECT 307
#define HTTP_BAD_REQUEST 400
#define HTTP_UNAUTHORIZED 401
#define HTTP_PAYMENT_REQUIRED 402
#define HTTP_FORBIDDEN 403
#define HTTP_NOT_FOUND 404
#define HTTP_METHOD_NOT_ALLOWED 405
#define HTTP_NOT_ACCEPTABLE 406
#define HTTP_PROXY_AUTHENTICATION_REQUIRED 407
#define HTTP_REQUEST_TIME_OUT 408
#define HTTP_CONFLICT 409
#define HTTP_GONE 410
#define HTTP_LENGTH_REQUIRED 411
#define HTTP_PRECONDITION_FAILED 412
#define HTTP_REQUEST_ENTITY_TOO_LARGE 413
#define HTTP_REQUEST_URI_TOO_LARGE 414
#define HTTP_UNSUPPORTED_MEDIA_TYPE 415
#define HTTP_RANGE_NOT_SATISFIABLE 416
#define HTTP_EXPECTATION_FAILED 417
#define HTTP_UNPROCESSABLE_ENTITY 422
#define HTTP_LOCKED 423
#define HTTP_FAILED_DEPENDENCY 424
#define HTTP_UPGRADE_REQUIRED 426
#define HTTP_INTERNAL_SERVER_ERROR 500
#define HTTP_NOT_IMPLEMENTED 501
#define HTTP_BAD_GATEWAY 502
#define HTTP_SERVICE_UNAVAILABLE 503
#define HTTP_GATEWAY_TIME_OUT 504
#define HTTP_VERSION_NOT_SUPPORTED 505
#define HTTP_VARIANT_ALSO_VARIES 506
#define HTTP_INSUFFICIENT_STORAGE 507
#define HTTP_NOT_EXTENDED 510

100代 インフォメーション
200代 正常終了
300代 リダイレクト(処理の変更通知)
400代 クライアント・エラー
500代 サーバ・エラー
こちら見てくれよな!

apache拡張モジュール 開発日記7 〜API・APRメモ〜

-- まとめ --
APRやAPIは全部網羅してるわけじゃないので、
かつ、正しいかもわからないので注意。

-- APR --
こちら参考
APRの関数はaprから始まる名前
Apache Portable Runtime
APIとはちょっと違うらしいが、同じようなもの?
載っていた説明は、C言語における移植性の確保を行ってくれる抽象レイヤー


メモリ管理
・apr_pool_t *
・領域の確保を行う(malloc相当)
・確保した領域について明示的なfreeは不要
 (1)領域の確保
   my_module_conf *conf = apr_palloc(p, sizeof(my_module_conf));

文字列操作
・C言語では複雑になりがちな文字列操作を簡単に
・返り値の領域はメモリプールから確保される
 (1)文字列のコピー
  char *str = apr_pstrdup(p, src);
 (2)文字列の連結
   char *str = apr_pstrcat(p, str1, str2, NULL);
 (3)文字列フォーマット
   char *str = apr_psprintf(p, "%d¥n", n);

動的配列
・apr_array_header_t*
・動的に拡張される配列
 (1)配列の生成
   apr_array_header_t *arr = apr_array_make(p, 10, sizeof(char *));
 (2)値の追加
   *(const char **)apr_array_push(arr) = val;
 (3)要素数
   arr -> nelts;
 (4)配列実体
   char **elts = arr -> elts;

テーブル
・apr_table_t*
・HTTPヘッダの処理などに仕様される key => value コンテナ
・動的に拡張される
 (1)テーブルの生成
   apr_table_t *tbl = apr_table_make(p, 12);
 (2)値のセット
   apr_table_set(tbl, key, val);
 (3)値の取得
   char *val = apr_table_get(tbl, key);
 (4)値の削除
   apr_table_unset(tbl, key);

-- API --
Apacheから提供されるAPI
ap_から始まる関数群

コンテンツ出力
 (1)ap_rputs(const char *str, request_rec *c);
 (2)ap_rwrite(const void *buf, int nbytes, request_rec *r);
 (3)ap_rprintf(requeat_rec *r, const char *fmt, ...);

ハンドラ返り値
 OK 処理成功
 DECLINED 次のモジュールに任せる
 HTTP_*
  HTTP_NOT_FOUND
  HTTP_FORBIDDEN
  HTTP_INTERNAL_SERVER_ERROR

モジュールの定義
・モジュールを適宜する構造体
  ディレクトリ毎の設定の初期化
  ディレクトリ毎の設定のマージ
  サーバ毎の設定の作成
  サーバ毎の設定のマージ
  設定値のリスト
  フックの登録

ディレクトリ毎の設定の初期化関数
static void *create_hello_cfg(apr_pool_t *p, char *dir){
  hello_cfg * cnf = apr_palloc(p, size_of(hello_cnf));
  cfg->msg = "Hello World";
  return (void *) cfg;
}

設定値を格納する構造体
typedef struct {
  char *msg;
} hello_cfg;

この初期化関数を、上にあるモジュール定義の、「ディレクトリ毎の設定の初期化」に書く。
 ex)create_hello_conf,



設定値のリスト
static const command_rec hello_cmds[] = {
  AP_INIT_TAKE1("hello,world",
         cmd_set_message,
         NULL,
         ACCESS_CONF,
         "Set mod_hello message"),
  {NULL}
};

cmd_set_message↓
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;
}

これも、上にあるモジュール定義の、「設定値のリスト」に書く。



-- memo --

typfrdef struct {
  int always;
  int expires;
}cookie_log_state;

cookie_log_state *clt = ap_get_module_config(r->server->module_config, &usertrack_module);
2つ目の引数のモジュールの設定を、configから読み込む。



const char *rname = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL);
推測だけど、リモートホスト(接続しているクライアントの名前)をrnameに入れる


ap_table_set(r->headers_out, "Set-Cookie", cookie);
ap_table_set(r->err_headers_out, "Set-Cookie", cookie);
ap_table_set(r->headers_out, "Location", r->unparsed_uri);

apache拡張モジュール 開発日記6 〜apxs ひな形解説〜

開発日記2で作ったひな形を解説っていうか
頭の中を整理するために、文字に起こそうと思います。
参考にしたページはこちらこちら


mod_test.c

 1 #include "httpd.h"
 2 #include "http_config.h"
 3 #include "http_protocol.h"
 4 #include "ap_config.h"
 5
 6 /* The sample content handler */
 7 static int test_handler(request_rec *r)
 8 {
 9   if (strcmp(r->handler, "test")) {
10     return DECLINED;
11   }
12
13   r->content_type = "text/html";
14   if (!r->header_only)
15     ap_rputs("The sample page from mod_test.c¥n", r);
16
17   return OK;
18 }
19
20 static void test_register_hooks(apr_pool_t *p)
21 {
22   ap_hook_handler(test_handler, NULL, NULL, APR_HOOK_MIDDLE);
23 }
24
25 /* Dispatch list for API hooks */ 
26 module AP_MODULE_DECLARE_DATA test_module = {
27   STANDARD20_MODULE_STUFF,
28   NULL, /* create per-dir config structures */
29   NULL, /* merge per-dir config structures */
30   NULL, /* create per-server config structures */
31   NULL, /* merge per-server config structures */
32   NULL, /* table of config file commands */
33   test_register_hooks /* register hooks */
34 };



参考ページにも書いてある通り、
test_handler()関数は、クライアントからのリクエストの処理に対する、レスポンスを生成する関数です。
引数のrequest_rec *rは、HTTPリクエストを表現した構造体です。
include/httpd.hで定義されています。
この構造体のまとめはそのうち書きますね。

具体的に、レスポンスを生成しているのは15行目です。
ap_rputs("文字列",リクエストポインタ);
で、このリクエストポインタが扱っている、リクエストに対するレスポンスのデータを
「文字列」にしている訳です。
実際に、http://localhost/test/を表示すると「文字列」と表示されます。
この「文字列」に、htmlタグを打っていくことによって、様々なページが作られるわけですね。
ちなみに、ap_aputs()関数は、Apacheが提供しているAPIですね。
そのうちAPIについてもまとめます。

15行目よりちょっと前の2つのifについて説明すると
9行目のifがリクエストのハンドラーがtestハンドラーかどうか調べて
testハンドラー以外だったらreturn DECLINED;する
DECLINEDは、このハンドラーは何もしないでapacheに処理を返すよ!の意味

ちなみにstrcmp(文字, 文字)関数は、文字列比較関数で
2つの文字が一緒だったら「0」を返して、違ったら「0以外」を返す関数です。
そして、C言語の仕様が、if()の評価は、0がfalse 0以外がtrue として扱われるので
上で説明した意味になります。

次の14行目のifは、
クライアントからのリクエストヘッダーが、HEADのものは、処理をしない。って意味です。
HEADリクエストの意味は「レスポンスのヘッダ部分だけ寄こせ」という意味で
「文字列」を表示する部分は、ヘッダの下の、データ部分に持たせます。
だから、このHEADリクエストに対するレスポンスに「文字列」なんて追加した日にはもう
夜も眠れないですね。
だからif(!r->header_only)で弾いてるわけです。
どうでもいいけど、HEADリクエストに、データ部分突っ込んで渡したらどうなるんでしょうね。

そして、return OKは処理成功って意味です。
DECLINEとかOKはApacheが決めてる定数っぽいので
何も考えないでそれreturnしてればいいと思う。
その定数をincludeでもしてるのかね?


それで、どのURLにアクセスしたら、このtestが処理されるのか?
っていうのは設定ファイルがあって、そこに設定すると初めて処理されることになります。
以下をhttpd.conf の適当なところに追加します。

<Location "/hoge/">
  SetHandler test
</Location>

これでhttp://localhost/hoge/にアクセスするとtestモジュールが起動されるわけっすね。



これでメインの文字表示の説明が終わったんで、あとの関数はさらっと説明で終わりますね。
詳しい説明も、そのうち。
test_register_hooks関数()については
Apacheの起動時に読み込まれて、このtest_handler()を処理するタイミングを
いつにするかを決める関数です。


test_moduleについては、このモジュールの初期設定やら
フックする関数やらを決めてる構造体です。
この構造体がApache本体に読み込まれて、どうのこうのされるんですねー。


っていうかJUGEM エディター使いにくいんだけど。普通の時に<br>を挿入してくれるはありがたいんだけど
どうてもいいところにも<br>挿入しやがる

apache拡張モジュール 開発日記5 〜form認証開発するよ!〜

勉強の一環として、フォーム認証を自分の力で開発するよ!

大雑把なアルゴリズムを書きます。

1.Webリクエストをうけたら、認証フォームを表示する
2.ユーザID,PASSWORDを受け取って、ユーザー認証する
3.正しければコンテンツレスポンス送信

ちょーおーざっぱ。
ちなみに、MOJULE.JPの小山浩之さんが既に開発してるので
それを参考にします。
がんばる

その小山さんが開発したmod_auth_formはこちら

apache拡張モジュール 開発日記4 〜apxs 再コンパイル〜

開発日記2で作ったtest.cを変更して再コンパイル方法。

開発
# vi /usr/local/apache2/3rdparty/test/mod_test.c

コンパイル
# /usr/local/apache2/bin/apxs -c /usr/local/apache2/3rdparty/test/mod_test.c

インストール
# /usr/local/apache2/bin/apxs -i -n test /usr/local/apache2/3rdparty/test/mod_test.la

-aオプション抜かしただけー。

ついでに再起動
# /usr/local/apache2/bin/apachectl graceful

memo
# /usr/local/apache2/bin/apxs -c /usr/local/apache2/3rdparty/auth_easy/mod_auth_easy.c
# /usr/local/apache2/bin/apxs -i -n auth_easy /usr/local/apache2/3rdparty/auth_easy/mod_auth_easy.la

# /usr/local/apache2/bin/apxs -c /usr/local/apache2/3rdparty/test/mod_test.c
# /usr/local/apache2/bin/apxs -i -n test /usr/local/apache2/3rdparty/test/mod_test.la

apache拡張モジュール 開発日記3 〜アクセス制御は簡単〜

http://module.jp/dist/InternetWeek2005-T16.pdf
の最後の方の資料に興味深いことが書いてあったのでメモ

アクセス制御は簡単
static int my_access_check(request_rec *r) {
  const char *cookie;
  cookie = apr_table_get(r->headers_in,“Cookie”);

  if (cookie != NULL && strcmp(cookie, “key=value”) != 0) {
    return OK;
  }

  return HTTP_FORBIDDEN;
}


calendar

S M T W T F S
    123
45678910
11121314151617
18192021222324
252627282930 
<< November 2018 >>

selected entries

categories

archives

recent comment

recommend

links

profile

search this site.

sponsored links

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM