mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-06-25 17:23:50 +08:00
Add API tests and test script
Co-authored-by: krau <71133316+krau@users.noreply.github.com>
This commit is contained in:
168
api/middleware_test.go
Normal file
168
api/middleware_test.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsIPAllowed(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
clientIP string
|
||||
allowedIPs []string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "exact match",
|
||||
clientIP: "192.168.1.100",
|
||||
allowedIPs: []string{"192.168.1.100"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "no match",
|
||||
clientIP: "192.168.1.100",
|
||||
allowedIPs: []string{"192.168.1.101"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wildcard",
|
||||
clientIP: "192.168.1.100",
|
||||
allowedIPs: []string{"*"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "CIDR match",
|
||||
clientIP: "192.168.1.100",
|
||||
allowedIPs: []string{"192.168.1.0/24"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "CIDR no match",
|
||||
clientIP: "192.168.2.100",
|
||||
allowedIPs: []string{"192.168.1.0/24"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "multiple IPs with match",
|
||||
clientIP: "192.168.1.100",
|
||||
allowedIPs: []string{"10.0.0.1", "192.168.1.100", "172.16.0.1"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "localhost",
|
||||
clientIP: "127.0.0.1",
|
||||
allowedIPs: []string{"127.0.0.1"},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := isIPAllowed(tt.clientIP, tt.allowedIPs)
|
||||
if result != tt.expected {
|
||||
t.Errorf("isIPAllowed(%q, %v) = %v, want %v",
|
||||
tt.clientIP, tt.allowedIPs, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMiddleware_NoAuth(t *testing.T) {
|
||||
// Create a test handler
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
})
|
||||
|
||||
// Create request
|
||||
req := httptest.NewRequest("GET", "/api/v1/tasks", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
// Apply middleware
|
||||
authMiddleware(handler).ServeHTTP(rec, req)
|
||||
|
||||
// When no token is configured, request should succeed or be unauthorized
|
||||
if rec.Code != http.StatusOK && rec.Code != http.StatusUnauthorized {
|
||||
t.Errorf("Expected status 200 or 401, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMiddleware_HealthCheck(t *testing.T) {
|
||||
// Create a test handler
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
})
|
||||
|
||||
// Create request to health endpoint
|
||||
req := httptest.NewRequest("GET", "/health", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
// Apply middleware
|
||||
authMiddleware(handler).ServeHTTP(rec, req)
|
||||
|
||||
// Health check should always work without auth
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200 for health check, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetClientIP(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
remoteAddr string
|
||||
xForwardedFor string
|
||||
xRealIP string
|
||||
expectedIP string
|
||||
}{
|
||||
{
|
||||
name: "RemoteAddr only",
|
||||
remoteAddr: "192.168.1.100:12345",
|
||||
expectedIP: "192.168.1.100",
|
||||
},
|
||||
{
|
||||
name: "X-Forwarded-For single",
|
||||
remoteAddr: "192.168.1.100:12345",
|
||||
xForwardedFor: "10.0.0.1",
|
||||
expectedIP: "10.0.0.1",
|
||||
},
|
||||
{
|
||||
name: "X-Forwarded-For multiple",
|
||||
remoteAddr: "192.168.1.100:12345",
|
||||
xForwardedFor: "10.0.0.1, 10.0.0.2, 10.0.0.3",
|
||||
expectedIP: "10.0.0.1",
|
||||
},
|
||||
{
|
||||
name: "X-Real-IP",
|
||||
remoteAddr: "192.168.1.100:12345",
|
||||
xRealIP: "10.0.0.1",
|
||||
expectedIP: "10.0.0.1",
|
||||
},
|
||||
{
|
||||
name: "X-Forwarded-For takes precedence",
|
||||
remoteAddr: "192.168.1.100:12345",
|
||||
xForwardedFor: "10.0.0.1",
|
||||
xRealIP: "10.0.0.2",
|
||||
expectedIP: "10.0.0.1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
req.RemoteAddr = tt.remoteAddr
|
||||
if tt.xForwardedFor != "" {
|
||||
req.Header.Set("X-Forwarded-For", tt.xForwardedFor)
|
||||
}
|
||||
if tt.xRealIP != "" {
|
||||
req.Header.Set("X-Real-IP", tt.xRealIP)
|
||||
}
|
||||
|
||||
result := getClientIP(req)
|
||||
if result != tt.expectedIP {
|
||||
t.Errorf("getClientIP() = %q, want %q", result, tt.expectedIP)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
105
test_api.sh
Executable file
105
test_api.sh
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/bin/bash
|
||||
|
||||
# API Test Script for SaveAny-Bot HTTP API
|
||||
|
||||
API_URL="http://localhost:18080"
|
||||
TOKEN="test-token-12345"
|
||||
HEADERS=(-H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json")
|
||||
|
||||
echo "=== Testing SaveAny-Bot HTTP API ==="
|
||||
echo
|
||||
|
||||
# Test 1: Health Check (no auth required)
|
||||
echo "1. Testing health check endpoint..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" "${API_URL}/health")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
BODY=$(echo "$RESPONSE" | sed '/HTTP_STATUS/d')
|
||||
|
||||
if [ "$HTTP_STATUS" = "200" ]; then
|
||||
echo "✓ Health check passed"
|
||||
echo " Response: $BODY"
|
||||
else
|
||||
echo "✗ Health check failed (HTTP $HTTP_STATUS)"
|
||||
echo " Response: $BODY"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 2: Unauthorized request (missing token)
|
||||
echo "2. Testing unauthorized request..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" "${API_URL}/api/v1/tasks")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
|
||||
if [ "$HTTP_STATUS" = "401" ]; then
|
||||
echo "✓ Correctly rejected unauthorized request"
|
||||
else
|
||||
echo "✗ Unexpected response (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 3: Invalid token
|
||||
echo "3. Testing invalid token..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" \
|
||||
-H "Authorization: Bearer wrong-token" \
|
||||
"${API_URL}/api/v1/tasks")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
|
||||
if [ "$HTTP_STATUS" = "401" ]; then
|
||||
echo "✓ Correctly rejected invalid token"
|
||||
else
|
||||
echo "✗ Unexpected response (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 4: List tasks (authorized)
|
||||
echo "4. Testing list tasks endpoint..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" \
|
||||
"${HEADERS[@]}" \
|
||||
"${API_URL}/api/v1/tasks")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
BODY=$(echo "$RESPONSE" | sed '/HTTP_STATUS/d')
|
||||
|
||||
if [ "$HTTP_STATUS" = "200" ]; then
|
||||
echo "✓ List tasks successful"
|
||||
echo " Response: $BODY"
|
||||
else
|
||||
echo "✗ List tasks failed (HTTP $HTTP_STATUS)"
|
||||
echo " Response: $BODY"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 5: Create task with missing parameters
|
||||
echo "5. Testing create task with missing parameters..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" \
|
||||
-X POST \
|
||||
"${HEADERS[@]}" \
|
||||
-d '{"telegram_url":""}' \
|
||||
"${API_URL}/api/v1/tasks")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
|
||||
if [ "$HTTP_STATUS" = "400" ]; then
|
||||
echo "✓ Correctly rejected invalid request"
|
||||
else
|
||||
echo "✗ Unexpected response (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 6: Get non-existent task
|
||||
echo "6. Testing get non-existent task..."
|
||||
RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" \
|
||||
"${HEADERS[@]}" \
|
||||
"${API_URL}/api/v1/tasks/nonexistent")
|
||||
HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS" | cut -d: -f2)
|
||||
|
||||
if [ "$HTTP_STATUS" = "404" ]; then
|
||||
echo "✓ Correctly returned 404 for non-existent task"
|
||||
else
|
||||
echo "✗ Unexpected response (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
echo
|
||||
|
||||
echo "=== API Tests Complete ==="
|
||||
echo
|
||||
echo "Note: Full integration testing requires:"
|
||||
echo " - Valid Telegram bot token in config"
|
||||
echo " - Bot running and connected to Telegram"
|
||||
echo " - Valid Telegram message URL to test downloads"
|
||||
Reference in New Issue
Block a user