Files
honeyDueAPI/internal/router/router_helpers.go
Trey T bec880886b Coverage priorities 1-5: test pure functions, extract interfaces, mock-based handler tests
- 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>
2026-04-01 20:30:09 -05:00

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()
}