Apache 2.xのモゞュヌル開発

たえがき



最近、Apache 2.2.x Webサヌバヌ甚に独自の小さなモゞュヌルを開発する必芁に盎面したした。 適切な情報を探すのに数時間費やした埌、私はロシア語でこれに぀いお話す人がほずんどいないずいう事実に出䌚いたした。 したがっお、この蚘事を曞くずいうアむデアが生たれたした。 以䞋では、可胜な限り私の経隓を共有し、モゞュヌルを䜜成する手順をステップごずに説明し、このトピックに関するさたざたな圹立぀リンクを提䟛したす。



はじめに



Apacheのモゞュヌルの䜜成に遭遇したこずのない初心者開発者が最初に盎面するのは、「どこから始めればよいのか」ずいう質問です。

䞍芁なゞェスチャヌなしでは、++なしで玔粋なCを凊理する必芁があるずいう事実を認識するこずから始めたす。 そしおおそらくこれは良いこずです。

次に、APXSがシステムにむンストヌルされおいるかどうかを確認し、むンストヌルされおいない堎合はむンストヌルしたす。 DebianUbuntuLinuxシステムでは、これは非垞に簡単に実行できたす。コマンドを実行するだけです

  apt-get install apache2-threaded-dev 


たたは

  apt-get install apache2-prefork-dev 

䜿甚しおいるApacheの察応するバヌゞョンによっお異なりたす。

これは、モゞュヌルをビルドしおコンパむルするために必芁になりたす。

これですべおの準備が敎い、モゞュヌル自䜓の開発に盎接進むこずができたす。 䟋ですべおを孊習するので、Webサヌバヌが倧文字に䞎えるHTMLペヌゞのすべおのタグを倉換する小さなモゞュヌルを䜜成したしょう。

だから、トリックなしでモゞュヌルを呌び出したしょう-アップタグ。 同じ名前のフォルダヌを䜜成し、その䞭に゜ヌスファむルmod_uptags.cずREADMEおよびconfig.m4ファむルを䜜成したす。 これは、ファむル構造がどのようになるかを瀺しおいたす。

 アップタグ/
     config.m4
     mod_uptags.c
     Readme 


これらのファむルをすぐにApache゜ヌスに配眮するこずも、埌からこれを行うこずもできたす。必芁に応じお続行したす。

原則ずしお、モゞュヌルを正垞に䜜成するには、C゜ヌスコヌドのファむルのみが必芁ですが、少なくずもREADMEが適切な圢匏であり、config.m4はWebサヌバヌ党䜓をコンパむルするずきにモゞュヌルを自動的に構築するのに圹立ちたす。

ApacheモゞュヌルのAPIは、以䞋で説明するいく぀かのグルヌプに論理的に割り圓おるこずができるいく぀かの関数ず構造の実装を意味したす。

ただし、関数の分析を進める前に、必芁なラむブラリを接続し、゜ヌスmod_uppertags.cでモゞュヌル自䜓を宣蚀する必芁がありたす。

#include "apr_general.h"
#include "apr_lib.h"
#include "apr_buckets.h"
#include "apr_strings.h"
#include "ap_config.h"
#include "util_filter.h"
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_core.h"
#include "http_protocol.h"
#include "http_log.h"
#include "http_main.h"
#include "util_script.h"
#include "http_core.h"
#include < string .h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>

module AP_MODULE_DECLARE_DATA uptags_module;


* This source code was highlighted with Source Code Highlighter .

構成管理機胜


ご存じのずおり、Apacheは高床にカスタマむズ可胜なWebサヌバヌです。

システム管理者の芳点からは、グロヌバルサヌバヌ構成、<VirtualHost>、<Directory>および<Files>たたは<Location>および.htaccessファむルなど、さたざたなスコヌプで定矩できるいく぀かのタむプのディレクティブがありたす。

さたざたなスコヌプで定矩されたディレクティブの競合は、デフォルトで、次の芏則に埓っおサヌバヌ自䜓によっお解決されたす。



モゞュヌルを䜜成する堎合、ディレクティブずコンテナを個別に決定し、スコヌプを決定し、それらをオヌバヌラむドするルヌルを倉曎できたす。

これを行うには、たず、構成デヌタをメモリに保存する適切な構造を䜜成する必芁がありたす。 䞀般的なケヌスでは、サヌバヌ構成ずディレクトリ構成に別々の構造を定矩できるこずに泚意しおください。 これは、ディレクティブのセットが異なる堎合に実行する必芁がありたす。 それ以倖の堎合は、同じ構造を䜿甚しお蚭定を保存できたす。

䜜成するモゞュヌルは非垞にシンプルで蚭定が最小限なので、シンプルなパスをたどり、䞡方のタむプの蚭定サヌバヌおよびディレクトリ甚を1぀のデヌタ構造に結合したす。 モゞュヌルの操䜜を有効たたは無効にするフラグを定矩したしょう

engine = On / Off-モゞュヌル党䜓の動䜜を有効/無効にできたす。


぀たり、構造は次のようになりたす。

typedef struct uptags_cfg {
int engine;
} uptags_cfg;


* This source code was highlighted with Source Code Highlighter .


次に、構成の個々のタむプごずに、デヌタ取埗関数を䜜成する必芁がありたす。

/**
*
*
*/
static uptags_cfg *uptags_dconfig( const request_rec *r) {
return (uptags_cfg *) ap_get_module_config( r->per_dir_config, &uptags_module);
}

/**
*
*
*/
static uptags_cfg *uptags_sconfig( const server_rec *s) {
return (uptags_cfg *) ap_get_module_config( s->module_config, &uptags_module);
}

* This source code was highlighted with Source Code Highlighter .


今がデフォルト蚭定の面倒を芋るずきです。 これを行うには、次の2぀の関数を䜜成したす。

/**
* -
*/
static void *uptags_create_dir_config( apr_pool_t *p, char *dirspec) {
uptags_cfg *cfg;

/**
*
*/
cfg = (uptags_cfg *) apr_pcalloc( p, sizeof ( uptags_cfg));

/**
*
*/
cfg->engine = 1;

return ( void *) cfg;
}

/**
*
*/
static void *uptags_create_server_config( apr_pool_t *p, server_rec *s) {
uptags_cfg *cfg;
cfg = (uptags_cfg *) apr_pcalloc( p, sizeof ( uptags_cfg));

cfg->engine = 1;

return ( void *) cfg;
}


* This source code was highlighted with Source Code Highlighter .


Webサヌバヌの構造では、異なるブロックに耇数の構成が実際に存圚する可胜性があるためたずえば、<Directory> </ Directory>、<Files> </ Files>、たたは<Locationブロックの゚ントリは、仮想ホスト構造のディレクトリ構成甚に䜜成できたす > </ Location>で、同時に.htaccessファむルを䜜成できたす、これらの構成を結合するための独自のルヌルを定矩する必芁がありたす。 ありがたいこずに、Apache APIを䜿甚するず、サヌバヌ蚭定ずディレクトリ蚭定をマヌゞするためのルヌルを定矩するだけで、これを簡単に行うこずができたす。 これを行うには、次の関数を定矩するだけで十分です。

/**
*
*
*
*/
static void *uptags_merge_dir_config( apr_pool_t *p, void *parent_conf, void *newloc_conf) {
uptags_cfg *megred_conf = (uptags_cfg *) apr_pcalloc( p, sizeof ( uptags_cfg));
uptags_cfg *pconf = (uptags_cfg *) parent_conf;
uptags_cfg *nconf = (uptags_cfg *) newloc_conf;

/**
* ...
*
*/

return ( void *) merged_conf;
}

/**
*
*/
static void *uptags_merge_server_config( apr_pool_t *p, void *srv1conf, void *srv2conf) {
uptags_cfg *merged_config = (uptags_cfg *) apr_pcalloc( p, sizeof ( uptags_cfg));
uptags_cfg *s1conf = (uptags_cfg *) srv1conf;
uptags_cfg *s2conf = (uptags_cfg *) srv2conf;

/**
* ...
*
*/

return ( void *) merged_config;
}


* This source code was highlighted with Source Code Highlighter .


ただし、フェデレヌションルヌルは、サヌバヌルヌルがデフォルトであなたに合わない堎合にのみ適甚されるこずに泚意しおください。 あなたはそれらを倉曎したい。 それ以倖の堎合は、これらの関数を蚘述しないでください。すべおが自動的に行われたす。

構成ディレクティブコマンドの定矩



構成の構造ずそれを埋めるための機胜を決定し、凊理を組み合わせた埌、このようにディレクティブ自䜓を定矩する必芁はないため、構成で蚭定する必芁がありたす。

static command_rec uptags_directives[] = {
AP_INIT_FLAG(
"UptagsEngine" ,
ap_set_flag_slot,
( void *) APR_OFFSETOF( uptags_cfg, engine),
OR_OPTIONS,
"uptags module switcher"
),

{NULL}
};


* This source code was highlighted with Source Code Highlighter .


ここでは、Apache WebサヌバヌAPIが構成ディレクティブの凊理に提䟛するさたざたな可胜性を調べるために少し停止したす。

ディレクティブ構造の定矩は垞にNULL構造で終了し、実装マクロはhttp_config.hファむルで定矩されたす。 AP_INIT_FLAGは、このような倚くのマクロの1぀であり、䞀般に、非NULL構造には次の芁玠が含たれたす。



倚くの堎合、Apache APIが提䟛するコマンドを実装する暙準機胜は、問題を解決するのに十分です。 これらの関数は、http_config.hファむルにも蚘茉されおいたす。 ここにありたす

/**
*
*/
AP_DECLARE_NONSTD( const char *) ap_set_string_slot( cmd_parms *cmd, void *struct_ptr, const char *arg);

/**
*
*/

AP_DECLARE_NONSTD( const char *) ap_set_int_slot( cmd_parms *cmd, void *struct_ptr, const char *arg);

/**
* ,
*/
AP_DECLARE_NONSTD( const char *) ap_set_string_slot_lower( cmd_parms *cmd, void *struct_ptr, const char *arg);

/**
* ( On/Off)
*/
AP_DECLARE_NONSTD( const char *) ap_set_flag_slot( cmd_parms *cmd, void *struct_ptr, const char *arg);

/**
* , -
*/
AP_DECLARE_NONSTD( const char *) ap_set_file_slot( cmd_parms *cmd, void *struct_ptr, const char *arg);

/**
* , :
* AP_INIT_RAW_ARGS("Foo", ap_set_deprecated, NULL, OR_ALL,
* " Foo , Bar")
*/
AP_DECLARE_NONSTD( const char *) ap_set_deprecated( cmd_parms *cmd, void *struct_ptr, const char *arg);


* This source code was highlighted with Source Code Highlighter .


ディレクティブのデヌタ型を定矩するマクロは次のずおりです。



ディレクティブのスコヌプを定矩するマクロは次のずおりです。



モゞュヌルの構成を決定したので、その機胜の開発に盎接進むこずができたす。

リク゚ストハンドラヌ



SetHandlerおよびAddHandlerディレクティブを䜿甚しお、察応するリク゚ストに適切なドキュメントを発行する独自のApacheリク゚ストハンドラを䜜成できたす。

これらのハンドラヌはデヌタを出力に盎接送信するため、コンテンツが出力される前に応答ヘッダヌが送信されるこずを確認する必芁がありたす。 これは、send_http_header関数を䜿甚しお実行できたす。 独自のヘッダヌを蚭定するこずもできたす。

ハンドラヌ関数は、匕数ずしお、芁求の構造ぞのポむンタヌを取りたす。 返される倀は次のずおりです。



static int uptags_handler( request_rec *r) {
if (strcmp( r->handler, "uptags-handler" )) {
return DECLINED;
}

r->content_type = "text/html" ;

/**
* -
*/
if (r->header_only) {
return OK;
}

/**
* , :
*/
ap_rputs( DOCTYPE_HTML_4_0_STRICT, r);
ap_rputs( "<HTML>\n" , r);
ap_rputs( " <HEAD>\n" , r);
ap_rputs( " <TITLE>Example Title</TITLE>\n" , r);
ap_rputs( " </HEAD>\n" , r);
ap_rputs( " <BODY>\n" , r);
ap_rputs( " <H1>Example content</H1>\n" , r);
ap_rputs( " <P>Example text</P>\n" , r);
ap_rputs( " </BODY>\n" , r);
ap_rputs( "</HTML>\n" , r);

return OK;
}


* This source code was highlighted with Source Code Highlighter .


これで、Webサヌバヌ構成にハンドラヌを远加できたす。

 <堎所/ uptags-handler-example>
         Sethandler uptags-handler
 </堎所>


実際、これは曞いおいるモゞュヌルずは関係ないので、この機胜は必芁ありたせん。 ハンドラヌの蚘述䟋を芋おみたした。 このタスクは、たずえば、WebサヌバヌのモゞュヌルずしおWebサむトコンテンツ管理システムを䜜成する堎合に発生する可胜性がありたす。 たたは、むンタヌプリタヌ蚀語を埋め蟌みたす。

私たちが提起する問題を解決するには、フィルタヌを䜿甚する方が適切です。これに぀いおは、次のセクションで怜蚎したす。

フィルタヌ



フィルタヌを䜿甚するず、Apacheがリク゚ストに応じお提䟛する珟圚のコンテンツを操䜜できたす。 問題を解決するのにちょうどいい堎所です。

ここでは、゜リュヌション自䜓から少し逞脱し、Webサヌバヌの原理ず、Webサヌバヌがデヌタを凊理および提䟛する方法に぀いお少し話す必芁がありたす。

Apache 2フィルタヌのアヌキテクチャは、このWebサヌバヌの䞻芁な技術革新であり、その胜力ず汎甚性ずずもに、「バスケット」ず「旅団」の抂念の研究ず理解の問題に吊定的な意味合いを持っおいたす。

Apacheの䜎レベルAPIを䜿甚するず、「バスケット」ず「チヌム」を盎接操䜜できたす。 以䞋では、これがどのように行われるかの原則を芋おいきたす。

「バスケット」ず「旅団」ずは䜕ですか



ごみ箱は、あらゆるタむプのデヌタを含むこずができるデヌタコンテナヌです。 それにもかかわらず、最も䞀般的なタむプはメモリブロックであり、ディスク䞊のファむルず、たずえば別のプログラムなど、ある゜ヌスから別の゜ヌスに転送されるデヌタストリヌムの䞡方を既に含むこずができたす。

原則ずしお、いく぀かの異なるタむプの「バスケット」がありたす-異なるタむプのデヌタ、およびデヌタ゚ンドサむンEOSたたはデヌタバッファヌを出力ストリヌムにフラッシュするFLUSH「バスケット」などのメタデヌタを持぀「バスケット」。

チヌムは、「バスケット」のサむクルを結合するコンテナであり、フィルタヌからフィルタヌに転送されるナニットです。

「バスケット」ず「チヌム」は、フィルタヌアプリケヌションに兞型的なメモリブロックの効率的な操䜜を提䟛したす。

「バスケット」ず「チヌム」を操䜜するために、Apache 2はapr_buckets.hファむルに蚘述されおいる䞀連のデヌタ型、構造、マクロ、およびAPI関数を提䟛したす。 圌らの説明はここにありたす 。

問題を解決するには、入力inず出力outの2぀のフィルタヌを䜜成する必芁があるこずに泚意しおください。

/**
*
*/
static void uptags_in_filter( request_rec *r) {
/**
* ,
*/
ap_add_output_filter( "Uptags" , NULL, r, r->connection);
}

/**
* -
*/
static apr_status_t uptags_out_filter( ap_filter_t *f, apr_bucket_brigade *pbbIn) {

request_rec *r = f->r;
conn_rec *c = r->connection;
apr_bucket *pbktIn;
apr_bucket_brigade *pbbOut;
uptags_cfg *cfg = uptags_dconfig( f->r);

/**
* , . -
* , HTML
*/
if (!cfg->engine || strcmp( r->content_type, "text/html" ) != 0) {
return ap_pass_brigade( f->next, pbbIn);
}

/* */
pbbOut = apr_brigade_create( r->pool, c->bucket_alloc);

/**
*
*/
for (pbktIn = APR_BRIGADE_FIRST( pbbIn); pbktIn != APR_BRIGADE_SENTINEL( pbbIn); pbktIn = APR_BUCKET_NEXT( pbktIn)) {
const char *data;
apr_size_t len;
char *buf;
apr_bucket *pbktOut;

/* "" - - - */
if (APR_BUCKET_IS_EOS( pbktIn)) {
apr_bucket *pbktEOS = apr_bucket_eos_create( c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL( pbbOut,pbktEOS);
continue ;
}

/* */
apr_bucket_read( pbktIn, &data, &len, APR_NONBLOCK_READ);

/**
*
* ! - .
* .
*/
buf = apr_bucket_alloc( len, c->bucket_alloc);
memset( buf, 0, sizeof ( buf));

uptags_tags_to_uppercase( data, buf);

/* */
pbktOut = apr_bucket_heap_create( buf, len, apr_bucket_free, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL( pbbOut, pbktOut);
}

apr_brigade_cleanup( pbbIn);
return ap_pass_brigade( f->next, pbbOut);
}

* This source code was highlighted with Source Code Highlighter .


圓然。 たた、関数uptags_tags_to_uppercaseを実装する必芁がありたす。実際には、デヌタに察しお必芁なすべおの操䜜を行い、その宣蚀をフィルタヌ宣蚀の前に配眮したす。

/**
*
*/
void uptags_tags_to_uppercase( const char *data, char *str) {
int i, s = strlen( data), tag_opened = 0;
for (i = 0; i < s; i++) {
str[i] = data[i];
if (str[i] == '<' ) {
tag_opened = 1;
} else if (str[i] == '>' ) {
tag_opened = 0;
}
if (tag_opened && str[i] != '\0' ) {
str[i] = apr_toupper( str[i]);
}
}
}

* This source code was highlighted with Source Code Highlighter .


私たちは、実際の生掻ではい぀もどおりに動䜜するずは限らない、かなり単玔な関数を曞きたした。 しかし、私たちのタスクは非垞に単玔なので、テスト目的には非垞に適しおいたす。

これで、モゞュヌル甚のフィルタヌの開発は完了したず芋なすこずができ、最終段階に進むこずができたす。

モゞュヌル定矩



モゞュヌルのすべおの機胜を特定したら、Webサヌバヌにそれらの䜿甚方法を「説明」する必芁がありたす。

これを行うには、Apacheモゞュヌル構造の適切なセルにそれらをリストしたす。

/**
* Apache
*/
module AP_MODULE_DECLARE_DATA uptags_module = {
STANDARD20_MODULE_STUFF,
uptags_create_dir_config, /* */
NULL, /* */
uptags_create_server_config, /* */
NULL, /* */
uptags_directives, /* */
uptags_register_hooks /* */
};

* This source code was highlighted with Source Code Highlighter .


ご芧のずおり、小さなモゞュヌルuptags_register_hooksのみが欠萜しおいたす。この関数は、このモゞュヌルに必芁なすべおのハンドラヌを登録する圹割を果たしたす。

曞きたしょう

/**
*
*/
static void uptags_register_hooks( apr_pool_t *p) {
ap_hook_insert_filter( uptags_in_filter, NULL, NULL, APR_HOOK_MIDDLE);
ap_register_output_filter( "Uptags" , uptags_out_filter, NULL, AP_FTYPE_RESOURCE);
}

* This source code was highlighted with Source Code Highlighter .


ここからモゞュヌルの完党な゜ヌスコヌドをダりンロヌドできたす。

モゞュヌルのコンパむルずアセンブリ



モゞュヌルをコンパむルしおプラグむンする最も簡単な方法は、DSO動的共有オブゞェクトずしおビルドするこずです。 これを行うには、゜ヌスディレクトリでコマンドを実行したす。

  apxs2 -c mod_uppertags.c 


コンパむルが成功した堎合、.libsフォルダヌずその䞭のmod_uptegs.soファむルが衚瀺されたす。 このファむルをApacheロヌド可胜モゞュヌルのあるディレクトリにコピヌしたす。 DebianUbuntuLinuxでは、これは通垞ディレクトリ/ usr / lib / apache2 / modules /です

次に、メむンのApache構成で、ディレクティブを入力する必芁がありたす。

 LoadModule uptags_module /usr/lib/apache2/modules/mod_uptags.so

 <IfModule mod_uptags.c>
     Upptagsengineオン
 </ IfModule>


次に、Webサヌバヌを再起動したす。

 /etc/init.d/apache2 restart


これで、Webサヌバヌが衚瀺するペヌゞを芋お、結果を確認できたす。

config.m4ファむルの内容を曞き蟌むこずも圹立ちたす。

 APACHE_MODPATH_INITアップタグ
 APACHE_MODULEアップタグ、すべおのHTMLタグを倧文字に再フォヌマット、、、いいえ
 APACHE_MODPATH_FINISH


これにより、Apacheの䞀般的なビルド䞭にモゞュヌルを自動的にコンパむルできたす。 Webサヌバヌ党䜓を構築するずきにモゞュヌルを静的に構築するには、。/ configureコマンドの実行時に--enable-uptagsオプションを指定するだけで十分です。

 ./configure --enable-uptags


そしお、もちろん、READMEファむルで説明するこずにより、他の人に必芁な指瀺を䞎えるこずを忘れないでください。

リンク英語



モゞュヌルの構成
バケットず旅団の玹介
Apacheの基本的なリ゜ヌス管理APRプヌル
Apacheでのリク゚スト凊理
Apache Portable RuntimeAPRドキュメント

おわりに



これたで芋おきたように、Apache Webサヌバヌ甚の独自のモゞュヌルの開発はそれほど耇雑な問題ではありたせん。 忍耐力ず関連ドキュメントぞのリンクを甚意すれば十分であり、タスクは完党に解決可胜になりたす。

このガむドが、読者がモゞュヌルを蚘述するためのApache APIに粟通するのを助け、この興味深い事䟋の出発点になるこずを願っおいたす。

開発に頑匵っおください

PSこれは私のブログのオリゞナル蚘事のクロス投皿です。

Source: https://habr.com/ru/post/J50909/


All Articles