Apache 模块开发与扩展
Apache Module Development and Extensions
概述 (Overview)
Apache模块开发是扩展服务器功能的强大方式。本文将详细介绍Apache模块的开发流程,包括模块结构、API使用、编译安装、调试技术以及常用模块扩展模式等核心技术。
Apache module development is a powerful way to extend server functionality. This article will detail the Apache module development process, including module structure, API usage, compilation and installation, debugging techniques, and common module extension patterns core technologies.
1. 模块开发环境搭建 (Module Development Environment Setup)
1.1 开发工具安装 (Development Tools Installation)
# Ubuntu/Debian系统
sudo apt-get update
sudo apt-get install apache2 apache2-dev build-essential libapr1-dev libaprutil1-dev
# CentOS/RHEL系统
sudo yum install httpd httpd-devel apr-devel apr-util-devel gcc make
# 验证安装
apxs -V
httpd -V
1.2 开发目录结构 (Development Directory Structure)
# 推荐的模块开发目录结构
/home/user/apache-modules/
├── mod_example/
│ ├── mod_example.c
│ ├── mod_example.h
│ ├── Makefile
│ └── README.md
├── mod_custom_auth/
│ ├── mod_custom_auth.c
│ └── Makefile
└── build/
├── config.log
└── config.status
2. 基本模块结构 (Basic Module Structure)
2.1 最简单的Apache模块 (Simplest Apache Module)
// mod_hello.c - 最简单的Apache模块示例
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
// 模块处理函数
static int hello_handler(request_rec *r)
{
// 检查是否应该处理这个请求
if (strcmp(r->handler, "hello")) {
return DECLINED;
}
// 设置内容类型
ap_set_content_type(r, "text/html");
// 发送响应
ap_rprintf(r, "<h1>Hello from Apache Module!</h1>");
ap_rprintf(r, "<p>Request URI: %s</p>", r->uri);
ap_rprintf(r, "<p>Server Name: %s</p>", r->server->server_hostname);
return OK;
}
// 注册钩子函数
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 structures
NULL, // merge per-dir config structures
NULL, // create per-server config structures
NULL, // merge per-server config structures
NULL, // table of config file commands
hello_register_hooks // register hooks
};
2.2 模块编译配置 (Module Compilation Configuration)
# Makefile - 模块编译配置
MODULE_NAME = mod_hello
SRC = mod_hello.c
APXS = apxs
# 编译目标
all: $(MODULE_NAME).so
# 编译模块
$(MODULE_NAME).so: $(SRC)
$(APXS) -c $(SRC)
# 安装模块
install: $(MODULE_NAME).so
$(APXS) -i -a $(MODULE_NAME).so
# 清理
clean:
rm -f *.so *.o *.lo *.la *.slo *.loT
rm -rf .libs
# 重新编译
rebuild: clean all
.PHONY: all install clean rebuild
3. 高级模块功能 (Advanced Module Features)
3.1 配置指令处理 (Configuration Directive Handling)
// mod_config_example.c - 配置指令处理示例
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
// 模块配置结构
typedef struct {
char *greeting;
int max_count;
} example_config;
// 创建服务器配置
static void *create_example_config(apr_pool_t *p, server_rec *s)
{
example_config *conf = apr_pcalloc(p, sizeof(example_config));
conf->greeting = "Hello";
conf->max_count = 100;
return conf;
}
// 配置指令处理函数
static const char *set_greeting(cmd_parms *cmd, void *cfg, const char *arg)
{
example_config *conf = ap_get_module_config(cmd->server->module_config,
&config_example_module);
conf->greeting = apr_pstrdup(cmd->pool, arg);
return NULL;
}
static const char *set_max_count(cmd_parms *cmd, void *cfg, const char *arg)
{
example_config *conf = ap_get_module_config(cmd->server->module_config,
&config_example_module);
conf->max_count = atoi(arg);
return NULL;
}
// 配置指令表
static const command_rec example_directives[] = {
AP_INIT_TAKE1("ExampleGreeting", set_greeting, NULL, RSRC_CONF,
"Set the greeting message"),
AP_INIT_TAKE1("ExampleMaxCount", set_max_count, NULL, RSRC_CONF,
"Set the maximum count"),
{NULL}
};
// 请求处理函数
static int config_example_handler(request_rec *r)
{
if (strcmp(r->handler, "config-example")) {
return DECLINED;
}
example_config *conf = ap_get_module_config(r->server->module_config,
&config_example_module);
ap_set_content_type(r, "text/html");
ap_rprintf(r, "<h1>%s from Config Module!</h1>", conf->greeting);
ap_rprintf(r, "<p>Max Count: %d</p>", conf->max_count);
return OK;
}
// 钩子注册
static void config_example_register_hooks(apr_pool_t *p)
{
ap_hook_handler(config_example_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
// 模块定义
module AP_MODULE_DECLARE_DATA config_example_module = {
STANDARD20_MODULE_STUFF,
NULL, // create per-dir config
NULL, // merge per-dir config
create_example_config, // create per-server config
NULL, // merge per-server config
example_directives, // configuration directives
config_example_register_hooks // register hooks
};
3.2 钩子函数使用 (Hook Function Usage)
// mod_hook_example.c - 钩子函数使用示例
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "ap_config.h"
// 日志钩子函数
static int log_request(request_rec *r)
{
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
"Request received: %s %s", r->method, r->uri);
return DECLINED;
}
// 访问控制钩子函数
static int check_access(request_rec *r)
{
// 简单的IP过滤示例
if (strncmp(r->useragent_ip, "192.168.1.", 10) == 0) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
"Access granted for IP: %s", r->useragent_ip);
return DECLINED;
}
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"Access denied for IP: %s", r->useragent_ip);
return HTTP_FORBIDDEN;
}
// 响应后处理钩子函数
static int fixup_response(request_rec *r)
{
// 添加自定义响应头
apr_table_set(r->headers_out, "X-Module-Version", "1.0");
apr_table_set(r->headers_out, "X-Processing-Time",
apr_psprintf(r->pool, "%ld", time(NULL) - r->request_time));
return DECLINED;
}
// 钩子注册
static void hook_example_register_hooks(apr_pool_t *p)
{
// 注册不同阶段的钩子
ap_hook_post_read_request(log_request, NULL, NULL, APR_HOOK_FIRST);
ap_hook_access_checker(check_access, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_fixups(fixup_response, NULL, NULL, APR_HOOK_LAST);
}
// 模块定义
module AP_MODULE_DECLARE_DATA hook_example_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, // configuration directives
hook_example_register_hooks // register hooks
};
4. 模块调试和测试 (Module Debugging and Testing)
4.1 调试配置 (Debug Configuration)
# httpd.conf - 调试配置
# 启用核心转储
CoreDumpDirectory /tmp
# 设置详细日志级别
LogLevel debug
# 启用模块特定调试
LogLevel info rewrite:trace3 mod_hello:trace6
# 自定义错误日志格式
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D %{HTTP_HOST}e" debug_combined
ErrorLog /var/log/apache2/debug.log
CustomLog /var/log/apache2/access.log debug_combined
4.2 调试脚本 (Debug Script)
#!/bin/bash
# module-debug.sh
debug_module() {
local module_name=${1:-"hello"}
echo "=== Apache Module Debug ==="
echo "Module: $module_name"
echo
# 1. 检查模块是否加载
echo "1. Module Loading Check:"
if apache2ctl -M | grep -q "$module_name"; then
echo " ✓ Module $module_name is loaded"
else
echo " ✗ Module $module_name is not loaded"
return 1
fi
# 2. 检查配置语法
echo
echo "2. Configuration Syntax Check:"
if apache2ctl configtest > /dev/null 2>&1; then
echo " ✓ Configuration syntax OK"
else
echo " ✗ Configuration syntax error"
apache2ctl configtest
return 1
fi
# 3. 重启Apache
echo
echo "3. Restarting Apache:"
sudo systemctl restart apache2
if [ $? -eq 0 ]; then
echo " ✓ Apache restarted successfully"
else
echo " ✗ Failed to restart Apache"
return 1
fi
# 4. 测试模块功能
echo
echo "4. Module Functionality Test:"
curl -s -H "Content-Type: text/html" "http://localhost/test?handler=$module_name"
# 5. 检查日志
echo
echo "5. Recent Log Entries:"
tail -10 /var/log/apache2/error.log | grep -i "$module_name"
echo
echo "Module debug completed!"
}
debug_module $1
5. 常用模块扩展模式 (Common Module Extension Patterns)
5.1 认证模块扩展 (Authentication Module Extension)
// mod_custom_auth.c - 自定义认证模块
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "apr_strings.h"
// 认证配置结构
typedef struct {
char *auth_db_path;
int enable_logging;
} custom_auth_config;
// 创建配置
static void *create_auth_config(apr_pool_t *p, server_rec *s)
{
custom_auth_config *conf = apr_pcalloc(p, sizeof(custom_auth_config));
conf->auth_db_path = "/etc/apache2/custom_auth.db";
conf->enable_logging = 1;
return conf;
}
// 认证处理函数
static int custom_auth_check(request_rec *r)
{
const char *auth_line;
char *user, *password;
// 获取认证头
auth_line = apr_table_get(r->headers_in, "Authorization");
if (!auth_line) {
return HTTP_UNAUTHORIZED;
}
// 解析Basic认证
if (strncmp(auth_line, "Basic ", 6) != 0) {
return HTTP_UNAUTHORIZED;
}
// 这里应该实现实际的认证逻辑
// 比如查询数据库、验证密码等
custom_auth_config *conf = ap_get_module_config(r->server->module_config,
&custom_auth_module);
if (conf->enable_logging) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
"Custom auth check for user: %s", user);
}
// 示例:简单验证
if (strcmp(user, "admin") == 0 && strcmp(password, "password") == 0) {
return OK;
}
return HTTP_UNAUTHORIZED;
}
// 注册认证钩子
static void custom_auth_register_hooks(apr_pool_t *p)
{
ap_hook_check_user_id(custom_auth_check, NULL, NULL, APR_HOOK_MIDDLE);
}
// 模块定义
module AP_MODULE_DECLARE_DATA custom_auth_module = {
STANDARD20_MODULE_STUFF,
NULL, // create per-dir config
NULL, // merge per-dir config
create_auth_config, // create per-server config
NULL, // merge per-server config
NULL, // configuration directives
custom_auth_register_hooks // register hooks
};
5.2 过滤器模块扩展 (Filter Module Extension)
// mod_content_filter.c - 内容过滤器模块
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "apr_strings.h"
// 过滤器上下文结构
typedef struct {
int enabled;
char *filter_name;
} filter_ctx;
// 输出过滤器函数
static apr_status_t content_output_filter(ap_filter_t *f,
apr_bucket_brigade *bb)
{
request_rec *r = f->r;
filter_ctx *ctx = f->ctx;
if (!ctx->enabled) {
// 如果未启用,直接传递给下一个过滤器
return ap_pass_brigade(f->next, bb);
}
// 这里可以实现内容修改逻辑
// 比如添加水印、修改HTML内容等
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"Content filter applied: %s", ctx->filter_name);
// 传递给下一个过滤器
return ap_pass_brigade(f->next, bb);
}
// 注册过滤器
static void content_filter_register_hooks(apr_pool_t *p)
{
ap_register_output_filter("CONTENT_FILTER", content_output_filter,
NULL, AP_FTYPE_CONTENT_SET);
}
// 模块定义
module AP_MODULE_DECLARE_DATA content_filter_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, // configuration directives
content_filter_register_hooks // register hooks
};
6. 模块部署和管理 (Module Deployment and Management)
6.1 模块安装脚本 (Module Installation Script)
#!/bin/bash
# module-install.sh
install_module() {
local module_file=${1:-"mod_example.so"}
local module_name=$(basename $module_file .so)
echo "=== Apache Module Installation ==="
echo "Module: $module_name"
echo
# 1. 复制模块文件
echo "1. Copying module file:"
sudo cp $module_file /usr/lib/apache2/modules/
sudo chown root:root /usr/lib/apache2/modules/$module_file
sudo chmod 644 /usr/lib/apache2/modules/$module_file
# 2. 启用模块
echo
echo "2. Enabling module:"
if sudo a2enmod $module_name; then
echo " ✓ Module $module_name enabled"
else
echo " ✗ Failed to enable module $module_name"
return 1
fi
# 3. 验证配置
echo
echo "3. Validating configuration:"
if sudo apache2ctl configtest; then
echo " ✓ Configuration is valid"
else
echo " ✗ Configuration error"
sudo a2dismod $module_name
return 1
fi
# 4. 重启Apache
echo
echo "4. Restarting Apache:"
if sudo systemctl restart apache2; then
echo " ✓ Apache restarted successfully"
else
echo " ✗ Failed to restart Apache"
return 1
fi
# 5. 验证模块加载
echo
echo "5. Verifying module load:"
if apache2ctl -M | grep -q $module_name; then
echo " ✓ Module $module_name is loaded"
else
echo " ✗ Module $module_name failed to load"
return 1
fi
echo
echo "Module installation completed successfully!"
}
install_module $1
6.2 模块卸载脚本 (Module Uninstallation Script)
#!/bin/bash
# module-uninstall.sh
uninstall_module() {
local module_name=${1:-"example"}
echo "=== Apache Module Uninstallation ==="
echo "Module: $module_name"
echo
# 1. 禁用模块
echo "1. Disabling module:"
if sudo a2dismod $module_name; then
echo " ✓ Module $module_name disabled"
else
echo " ✗ Failed to disable module $module_name"
fi
# 2. 验证配置
echo
echo "2. Validating configuration:"
if sudo apache2ctl configtest; then
echo " ✓ Configuration is valid"
else
echo " ✗ Configuration error"
sudo a2enmod $module_name
return 1
fi
# 3. 重启Apache
echo
echo "3. Restarting Apache:"
if sudo systemctl restart apache2; then
echo " ✓ Apache restarted successfully"
else
echo " ✗ Failed to restart Apache"
return 1
fi
# 4. 删除模块文件
echo
echo "4. Removing module file:"
if [ -f "/usr/lib/apache2/modules/mod_${module_name}.so" ]; then
sudo rm -f /usr/lib/apache2/modules/mod_${module_name}.so
echo " ✓ Module file removed"
else
echo " - Module file not found"
fi
echo
echo "Module uninstallation completed!"
}
uninstall_module $1
小结 (Summary)
通过本文学习,你应该掌握:
- Apache模块开发环境的搭建方法
- 基本模块结构和编译配置
- 高级模块功能,包括配置指令处理和钩子函数使用
- 模块调试和测试技术
- 常用模块扩展模式(认证、过滤器等)
- 模块部署和管理脚本
Apache模块开发是扩展服务器功能的强大工具,通过自定义模块可以实现各种特定需求。在下一篇文章中,我们将详细介绍Apache集群部署技术。