diff --git a/internal/server/handlers.go b/internal/server/handlers.go index ab5da75..949844d 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -616,3 +616,33 @@ func (s *Server) handlePrefixDetail() http.HandlerFunc { } } } + +// handleIPRedirect looks up the prefix containing the IP and redirects to its detail page +func (s *Server) handleIPRedirect() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ip := chi.URLParam(r, "ip") + if ip == "" { + http.Error(w, "IP parameter is required", http.StatusBadRequest) + + return + } + + // Look up AS information for the IP (which includes the prefix) + asInfo, err := s.db.GetASInfoForIP(ip) + if err != nil { + if errors.Is(err, database.ErrInvalidIP) { + http.Error(w, "Invalid IP address", http.StatusBadRequest) + } else if errors.Is(err, database.ErrNoRoute) { + http.Error(w, "No route found for this IP", http.StatusNotFound) + } else { + s.logger.Error("Failed to look up IP", "error", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + } + + return + } + + // Redirect to the prefix detail page + http.Redirect(w, r, "/prefix/"+asInfo.Prefix, http.StatusSeeOther) + } +} diff --git a/internal/server/routes.go b/internal/server/routes.go index cce24cd..59c7828 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -28,6 +28,7 @@ func (s *Server) setupRoutes() { // AS and prefix detail pages r.Get("/as/{asn}", s.handleASDetail()) r.Get("/prefix/{prefix}", s.handlePrefixDetail()) + r.Get("/ip/{ip}", s.handleIPRedirect()) // API routes r.Route("/api/v1", func(r chi.Router) {