Initial commit: mod_reqin_log Apache module
Features: - JSON logging of HTTP requests to Unix domain socket - Configurable HTTP headers logging (flat JSON structure) - Header value truncation and count limits - Automatic reconnect on socket disconnection - Error reporting with throttling Configuration directives: - JsonSockLogEnabled: Enable/disable logging - JsonSockLogSocket: Unix socket path - JsonSockLogHeaders: List of headers to log - JsonSockLogMaxHeaders: Maximum headers to log - JsonSockLogMaxHeaderValueLen: Max header value length - JsonSockLogReconnectInterval: Reconnect delay - JsonSockLogErrorReportInterval: Error log throttle Includes: - Module source code (src/) - Unit and integration tests (tests/, scripts/) - Documentation (README.md, architecture.yml) - Build configuration (CMakeLists.txt, Makefile) - Packaging (deb/rpm) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
317
scripts/test_unix_socket.sh
Executable file
317
scripts/test_unix_socket.sh
Executable file
@ -0,0 +1,317 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# test_unix_socket.sh - Integration test for mod_reqin_log Unix socket logging
|
||||
#
|
||||
# This test verifies that:
|
||||
# 1. The module connects to a Unix socket
|
||||
# 2. HTTP requests generate JSON log entries
|
||||
# 3. Log entries are properly formatted and sent to the socket
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
SOCKET_PATH="/tmp/mod_reqin_log_test.sock"
|
||||
LOG_OUTPUT="/tmp/mod_reqin_log_output.jsonl"
|
||||
APACHE_PORT="${APACHE_PORT:-8080}"
|
||||
TIMEOUT=30
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() {
|
||||
echo -e "${YELLOW}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_pass() {
|
||||
echo -e "${GREEN}[PASS]${NC} $1"
|
||||
}
|
||||
|
||||
log_fail() {
|
||||
echo -e "${RED}[FAIL]${NC} $1"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
log_info "Cleaning up..."
|
||||
rm -f "$SOCKET_PATH" "$LOG_OUTPUT"
|
||||
pkill -f "socket_listener.py" 2>/dev/null || true
|
||||
pkill -f "apache.*test" 2>/dev/null || true
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
# Check dependencies
|
||||
check_dependencies() {
|
||||
log_info "Checking dependencies..."
|
||||
if ! command -v curl &> /dev/null; then
|
||||
log_fail "curl is required but not installed"
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
log_fail "python3 is required but not installed"
|
||||
exit 1
|
||||
fi
|
||||
log_pass "Dependencies OK"
|
||||
}
|
||||
|
||||
# Start Unix socket listener that logs received data
|
||||
start_socket_listener() {
|
||||
log_info "Starting Unix socket listener on $SOCKET_PATH..."
|
||||
rm -f "$SOCKET_PATH"
|
||||
|
||||
# Use Python script to listen on Unix socket
|
||||
python3 /build/scripts/socket_listener.py "$SOCKET_PATH" -o "$LOG_OUTPUT" &
|
||||
LISTENER_PID=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
if ! kill -0 $LISTENER_PID 2>/dev/null; then
|
||||
log_fail "Failed to start socket listener"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_pass "Socket listener started (PID: $LISTENER_PID)"
|
||||
}
|
||||
|
||||
# Create Apache test configuration
|
||||
create_apache_config() {
|
||||
log_info "Creating Apache test configuration..."
|
||||
|
||||
cat > /tmp/httpd_test.conf << EOF
|
||||
ServerRoot "/etc/httpd"
|
||||
Listen $APACHE_PORT
|
||||
ServerName localhost
|
||||
|
||||
LoadModule reqin_log_module /build/.libs/mod_reqin_log.so
|
||||
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||
LoadModule authz_core_module modules/mod_authz_core.so
|
||||
LoadModule dir_module modules/mod_dir.so
|
||||
LoadModule mime_module modules/mod_mime.so
|
||||
LoadModule unixd_module modules/mod_unixd.so
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
|
||||
User apache
|
||||
Group apache
|
||||
|
||||
TypesConfig /etc/mime.types
|
||||
DirectoryIndex index.html
|
||||
|
||||
JsonSockLogEnabled On
|
||||
JsonSockLogSocket "$SOCKET_PATH"
|
||||
JsonSockLogHeaders X-Request-Id User-Agent X-Test-Header
|
||||
JsonSockLogMaxHeaders 10
|
||||
JsonSockLogMaxHeaderValueLen 256
|
||||
JsonSockLogReconnectInterval 5
|
||||
JsonSockLogErrorReportInterval 5
|
||||
|
||||
<VirtualHost *:$APACHE_PORT>
|
||||
DocumentRoot /var/www/html
|
||||
<Directory /var/www/html>
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
||||
ErrorLog /dev/stderr
|
||||
LogLevel warn
|
||||
EOF
|
||||
|
||||
log_pass "Apache configuration created"
|
||||
}
|
||||
|
||||
# Start Apache with test configuration
|
||||
start_apache() {
|
||||
log_info "Starting Apache with mod_reqin_log..."
|
||||
|
||||
# Create document root if needed
|
||||
mkdir -p /var/www/html
|
||||
echo "<html><body><h1>Test</h1></body></html>" > /var/www/html/index.html
|
||||
|
||||
# Check socket exists
|
||||
if [ ! -S "$SOCKET_PATH" ]; then
|
||||
log_fail "Socket file does not exist: $SOCKET_PATH"
|
||||
ls -la /tmp/*.sock 2>&1 || true
|
||||
exit 1
|
||||
fi
|
||||
log_info "Socket file exists: $SOCKET_PATH"
|
||||
ls -la "$SOCKET_PATH"
|
||||
|
||||
# Start Apache and capture stderr
|
||||
httpd -f /tmp/httpd_test.conf -DFOREGROUND 2>&1 &
|
||||
APACHE_PID=$!
|
||||
|
||||
# Wait for Apache to start
|
||||
sleep 2
|
||||
|
||||
if ! kill -0 $APACHE_PID 2>/dev/null; then
|
||||
log_fail "Failed to start Apache"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_pass "Apache started (PID: $APACHE_PID)"
|
||||
|
||||
# Wait for Apache workers to initialize and connect to socket
|
||||
log_info "Waiting for Apache workers to initialize..."
|
||||
sleep 3
|
||||
}
|
||||
|
||||
# Send test HTTP requests
|
||||
send_test_requests() {
|
||||
log_info "Sending test HTTP requests..."
|
||||
|
||||
# Health check first
|
||||
local retries=5
|
||||
while [ $retries -gt 0 ]; do
|
||||
if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$APACHE_PORT/" | grep -q "200"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
retries=$((retries - 1))
|
||||
done
|
||||
|
||||
if [ $retries -eq 0 ]; then
|
||||
log_fail "Apache health check failed"
|
||||
return 1
|
||||
fi
|
||||
log_info "Apache health check passed"
|
||||
|
||||
# Request 1: Basic GET
|
||||
curl -s "http://localhost:$APACHE_PORT/" > /dev/null
|
||||
sleep 0.5
|
||||
|
||||
# Request 2: With custom headers
|
||||
curl -s -H "X-Request-Id: test-12345" "http://localhost:$APACHE_PORT/" > /dev/null
|
||||
sleep 0.5
|
||||
|
||||
# Request 3: POST request
|
||||
curl -s -X POST -d "test=data" "http://localhost:$APACHE_PORT/" > /dev/null
|
||||
sleep 0.5
|
||||
|
||||
# Request 4: With User-Agent
|
||||
curl -s -A "TestAgent/1.0" "http://localhost:$APACHE_PORT/api/test" > /dev/null
|
||||
sleep 0.5
|
||||
|
||||
# Request 5: Multiple headers
|
||||
curl -s \
|
||||
-H "X-Request-Id: req-abc" \
|
||||
-H "X-Test-Header: header-value" \
|
||||
-H "User-Agent: Mozilla/5.0" \
|
||||
"http://localhost:$APACHE_PORT/page" > /dev/null
|
||||
sleep 1
|
||||
|
||||
log_pass "Test requests sent"
|
||||
}
|
||||
|
||||
# Verify log output
|
||||
verify_logs() {
|
||||
log_info "Verifying log output..."
|
||||
|
||||
if [ ! -f "$LOG_OUTPUT" ]; then
|
||||
log_fail "Log file not created"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local log_count=$(wc -l < "$LOG_OUTPUT")
|
||||
if [ "$log_count" -lt 1 ]; then
|
||||
log_fail "Expected at least 1 log entry, got $log_count"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_pass "Received $log_count log entries"
|
||||
|
||||
# Show all log entries
|
||||
log_info "Log file contents:"
|
||||
cat "$LOG_OUTPUT"
|
||||
|
||||
# Verify JSON format
|
||||
log_info "Validating JSON format..."
|
||||
local invalid_json=0
|
||||
while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
if ! echo "$line" | python3 -m json.tool > /dev/null 2>&1; then
|
||||
log_fail "Invalid JSON: $line"
|
||||
invalid_json=1
|
||||
fi
|
||||
fi
|
||||
done < "$LOG_OUTPUT"
|
||||
|
||||
if [ $invalid_json -eq 0 ]; then
|
||||
log_pass "All JSON entries are valid"
|
||||
fi
|
||||
|
||||
# Verify required fields
|
||||
log_info "Checking required fields..."
|
||||
local first_line=$(head -1 "$LOG_OUTPUT")
|
||||
|
||||
local required_fields=("time" "timestamp" "src_ip" "dst_ip" "method" "path" "host")
|
||||
local missing_fields=0
|
||||
|
||||
for field in "${required_fields[@]}"; do
|
||||
if ! echo "$first_line" | grep -q "\"$field\":"; then
|
||||
log_fail "Missing required field: $field"
|
||||
missing_fields=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $missing_fields -eq 0 ]; then
|
||||
log_pass "All required fields present"
|
||||
fi
|
||||
|
||||
# Verify header logging
|
||||
log_info "Checking header logging..."
|
||||
if grep -q '"header_X-Request-Id"' "$LOG_OUTPUT"; then
|
||||
log_pass "Custom headers are logged"
|
||||
else
|
||||
log_info "Custom headers test skipped (no X-Request-Id in requests)"
|
||||
fi
|
||||
|
||||
# Verify HTTP methods
|
||||
log_info "Checking HTTP methods..."
|
||||
if grep -q '"method":"GET"' "$LOG_OUTPUT"; then
|
||||
log_pass "GET method logged"
|
||||
fi
|
||||
|
||||
if grep -q '"method":"POST"' "$LOG_OUTPUT"; then
|
||||
log_pass "POST method logged"
|
||||
fi
|
||||
|
||||
# Show sample log entry
|
||||
log_info "Sample log entry (formatted):"
|
||||
head -1 "$LOG_OUTPUT" | python3 -m json.tool 2>/dev/null || head -1 "$LOG_OUTPUT"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main test runner
|
||||
main() {
|
||||
echo "========================================"
|
||||
echo "mod_reqin_log Unix Socket Integration Test"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
check_dependencies
|
||||
start_socket_listener
|
||||
create_apache_config
|
||||
start_apache
|
||||
send_test_requests
|
||||
|
||||
log_info "Waiting for logs to be written..."
|
||||
sleep 2
|
||||
|
||||
verify_logs
|
||||
local result=$?
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
if [ $result -eq 0 ]; then
|
||||
echo -e "${GREEN}All tests passed!${NC}"
|
||||
else
|
||||
echo -e "${RED}Some tests failed!${NC}"
|
||||
fi
|
||||
echo "========================================"
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user