Files
Charon/backend/internal/api/handlers/system_handler.go
GitHub Actions d7939bed70 feat: add ManualDNSChallenge component and related hooks for manual DNS challenge management
- Implemented `useManualChallenge`, `useChallengePoll`, and `useManualChallengeMutations` hooks for managing manual DNS challenges.
- Created tests for the `useManualChallenge` hooks to ensure correct fetching and mutation behavior.
- Added `ManualDNSChallenge` component for displaying challenge details and actions.
- Developed end-to-end tests for the Manual DNS Provider feature, covering provider selection, challenge UI, and accessibility compliance.
- Included error handling tests for verification failures and network errors.
2026-01-12 04:01:40 +00:00

76 lines
1.6 KiB
Go

package handlers
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type SystemHandler struct{}
func NewSystemHandler() *SystemHandler {
return &SystemHandler{}
}
type MyIPResponse struct {
IP string `json:"ip"`
Source string `json:"source"`
}
// GetMyIP returns the client's public IP address
func (h *SystemHandler) GetMyIP(c *gin.Context) {
// Try to get the real IP from various headers (in order of preference)
// This handles proxies, load balancers, and CDNs
ip := getClientIP(c.Request)
source := "direct"
switch {
case c.GetHeader("X-Forwarded-For") != "":
source = "X-Forwarded-For"
case c.GetHeader("X-Real-IP") != "":
source = "X-Real-IP"
case c.GetHeader("CF-Connecting-IP") != "":
source = "Cloudflare"
}
c.JSON(http.StatusOK, MyIPResponse{
IP: ip,
Source: source,
})
}
// getClientIP extracts the real client IP from the request
// Checks headers in order of trust/reliability
func getClientIP(r *http.Request) string {
// Cloudflare
if ip := r.Header.Get("CF-Connecting-IP"); ip != "" {
return ip
}
// Other CDNs/proxies
if ip := r.Header.Get("X-Real-IP"); ip != "" {
return ip
}
// Standard proxy header (can be a comma-separated list)
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
// Take the first IP in the list (client IP)
ips := strings.Split(forwarded, ",")
if len(ips) > 0 {
return strings.TrimSpace(ips[0])
}
}
// Fallback to RemoteAddr (format: "IP:port")
if ip := r.RemoteAddr; ip != "" {
// Remove port if present
if idx := strings.LastIndex(ip, ":"); idx != -1 {
return ip[:idx]
}
return ip
}
return "unknown"
}