- Priority 1: Test NewSendEmailTask + NewSendPushTask (5 tests) - Priority 2: Test customHTTPErrorHandler — all 15+ branches (21 tests) - Priority 3: Extract Enqueuer interface + payload builders in worker pkg (5 tests) - Priority 4: Extract ClassifyFile/ComputeRelPath in migrate-encrypt (6 tests) - Priority 5: Define Handler interfaces, refactor to accept them, mock-based tests (14 tests) - Fix .gitignore: /worker instead of worker to stop ignoring internal/worker/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
116 lines
3.7 KiB
Go
116 lines
3.7 KiB
Go
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/treytartt/honeydue-api/internal/monitoring"
|
|
)
|
|
|
|
// CorsOrigins returns the CORS allowed origins based on debug mode.
|
|
func CorsOrigins(debug bool, configuredOrigins []string) []string {
|
|
if debug {
|
|
return []string{
|
|
"http://localhost:3000",
|
|
"http://localhost:3001",
|
|
"http://localhost:8080",
|
|
"http://localhost:8000",
|
|
"http://127.0.0.1:3000",
|
|
"http://127.0.0.1:3001",
|
|
"http://127.0.0.1:8080",
|
|
"http://127.0.0.1:8000",
|
|
}
|
|
}
|
|
if len(configuredOrigins) > 0 {
|
|
return configuredOrigins
|
|
}
|
|
return []string{
|
|
"https://api.myhoneydue.com",
|
|
"https://myhoneydue.com",
|
|
"https://admin.myhoneydue.com",
|
|
}
|
|
}
|
|
|
|
// ShouldSkipTimeout returns true for paths that should bypass timeout middleware.
|
|
func ShouldSkipTimeout(path, host, adminHost string) bool {
|
|
return (adminHost != "" && host == adminHost) ||
|
|
strings.HasPrefix(path, "/_next") ||
|
|
strings.HasSuffix(path, "/ws")
|
|
}
|
|
|
|
// ShouldSkipBodyLimit returns true for webhook endpoints.
|
|
func ShouldSkipBodyLimit(path string) bool {
|
|
return strings.HasPrefix(path, "/api/subscription/webhook")
|
|
}
|
|
|
|
// ShouldSkipGzip returns true for media endpoints.
|
|
func ShouldSkipGzip(path string) bool {
|
|
return strings.HasPrefix(path, "/api/media/")
|
|
}
|
|
|
|
// ParseEndpoint splits "GET /api/foo" into method and path.
|
|
func ParseEndpoint(endpoint string) (method, path string) {
|
|
parts := strings.SplitN(endpoint, " ", 2)
|
|
if len(parts) == 2 {
|
|
return parts[0], parts[1]
|
|
}
|
|
return endpoint, ""
|
|
}
|
|
|
|
// AllowedProxyHosts builds the list of hosts allowed for admin proxy.
|
|
func AllowedProxyHosts(adminHost string) []string {
|
|
var hosts []string
|
|
if adminHost != "" {
|
|
hosts = append(hosts, adminHost)
|
|
}
|
|
hosts = append(hosts, "localhost:3001", "127.0.0.1:3001", "localhost:8000", "127.0.0.1:8000")
|
|
return hosts
|
|
}
|
|
|
|
// DetermineAdminRoute decides how to route admin subdomain requests.
|
|
func DetermineAdminRoute(path string) string {
|
|
if strings.HasPrefix(path, "/admin") {
|
|
return "redirect"
|
|
}
|
|
if strings.HasPrefix(path, "/api/") {
|
|
return "passthrough"
|
|
}
|
|
return "proxy"
|
|
}
|
|
|
|
// FormatPrometheusMetrics converts HTTP stats to Prometheus text format.
|
|
func FormatPrometheusMetrics(stats monitoring.HTTPStats) string {
|
|
var b strings.Builder
|
|
|
|
b.WriteString("# HELP http_requests_total Total number of HTTP requests.\n")
|
|
b.WriteString("# TYPE http_requests_total counter\n")
|
|
for statusCode, count := range stats.ByStatusCode {
|
|
fmt.Fprintf(&b, "http_requests_total{status_code=\"%d\"} %d\n", statusCode, count)
|
|
}
|
|
|
|
b.WriteString("# HELP http_endpoint_requests_total Total requests per endpoint.\n")
|
|
b.WriteString("# TYPE http_endpoint_requests_total counter\n")
|
|
for endpoint, epStats := range stats.ByEndpoint {
|
|
method, path := ParseEndpoint(endpoint)
|
|
fmt.Fprintf(&b, "http_endpoint_requests_total{method=\"%s\",path=\"%s\"} %d\n", method, path, epStats.Count)
|
|
}
|
|
|
|
b.WriteString("# HELP http_request_duration_ms Average request duration in milliseconds per endpoint.\n")
|
|
b.WriteString("# TYPE http_request_duration_ms gauge\n")
|
|
for endpoint, epStats := range stats.ByEndpoint {
|
|
method, path := ParseEndpoint(endpoint)
|
|
fmt.Fprintf(&b, "http_request_duration_ms{method=\"%s\",path=\"%s\",quantile=\"avg\"} %.2f\n", method, path, epStats.AvgLatencyMs)
|
|
fmt.Fprintf(&b, "http_request_duration_ms{method=\"%s\",path=\"%s\",quantile=\"p95\"} %.2f\n", method, path, epStats.P95LatencyMs)
|
|
}
|
|
|
|
b.WriteString("# HELP http_error_rate Overall error rate (4xx+5xx / total).\n")
|
|
b.WriteString("# TYPE http_error_rate gauge\n")
|
|
fmt.Fprintf(&b, "http_error_rate %.4f\n", stats.ErrorRate)
|
|
|
|
b.WriteString("# HELP http_requests_per_minute Current request rate.\n")
|
|
b.WriteString("# TYPE http_requests_per_minute gauge\n")
|
|
fmt.Fprintf(&b, "http_requests_per_minute %.2f\n", stats.RequestsPerMinute)
|
|
|
|
return b.String()
|
|
}
|