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>
318 lines
8.0 KiB
Bash
Executable File
318 lines
8.0 KiB
Bash
Executable File
#!/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 "$@"
|