Fix IPv6 prefix length links to use separate /prefixlength6/<len> route
The prefix length links for IPv6 prefixes were incorrectly pointing to /prefixlength/<len> which would show IPv4 prefixes. Added a new route /prefixlength6/<len> specifically for IPv6 prefixes and updated the template to use the correct URL based on whether displaying IPv4 or IPv6 prefix distributions. Also refactored handlePrefixLength to explicitly handle only IPv4 prefixes and created handlePrefixLength6 for IPv6 prefixes, removing the ambiguous auto-detection based on mask length value.
This commit is contained in:
parent
1ec0b3e7ca
commit
2f96141e48
@ -20,6 +20,11 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
// statsContextTimeout is the timeout for stats API operations
|
||||
statsContextTimeout = 4 * time.Second
|
||||
)
|
||||
|
||||
// handleRoot returns a handler that redirects to /status
|
||||
func (s *Server) handleRoot() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
@ -81,7 +86,7 @@ func (s *Server) handleStatusJSON() http.HandlerFunc {
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a 4 second timeout context for this request
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 4*time.Second)
|
||||
ctx, cancel := context.WithTimeout(r.Context(), statsContextTimeout)
|
||||
defer cancel()
|
||||
|
||||
metrics := s.streamer.GetMetrics()
|
||||
@ -215,7 +220,7 @@ func (s *Server) handleStats() http.HandlerFunc {
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a 4 second timeout context for this request
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 4*time.Second)
|
||||
ctx, cancel := context.WithTimeout(r.Context(), statsContextTimeout)
|
||||
defer cancel()
|
||||
|
||||
// Check if context is already cancelled
|
||||
@ -762,7 +767,7 @@ func (s *Server) handleIPRedirect() http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// handlePrefixLength shows a random sample of prefixes with the specified mask length
|
||||
// handlePrefixLength shows a random sample of IPv4 prefixes with the specified mask length
|
||||
func (s *Server) handlePrefixLength() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
lengthStr := chi.URLParam(r, "length")
|
||||
@ -779,22 +784,107 @@ func (s *Server) handlePrefixLength() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Determine IP version based on mask length
|
||||
const (
|
||||
maxIPv4MaskLength = 32
|
||||
maxIPv6MaskLength = 128
|
||||
)
|
||||
var ipVersion int
|
||||
if maskLength <= maxIPv4MaskLength {
|
||||
ipVersion = 4
|
||||
} else if maskLength <= maxIPv6MaskLength {
|
||||
ipVersion = 6
|
||||
} else {
|
||||
// Validate IPv4 mask length
|
||||
const maxIPv4MaskLength = 32
|
||||
if maskLength < 0 || maskLength > maxIPv4MaskLength {
|
||||
http.Error(w, "Invalid IPv4 mask length", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const ipVersion = 4
|
||||
|
||||
// Get random sample of prefixes
|
||||
const maxPrefixes = 500
|
||||
prefixes, err := s.db.GetRandomPrefixesByLengthContext(r.Context(), maskLength, ipVersion, maxPrefixes)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get prefixes by length", "error", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Sort prefixes for display
|
||||
sort.Slice(prefixes, func(i, j int) bool {
|
||||
// First compare by IP version
|
||||
if prefixes[i].IPVersion != prefixes[j].IPVersion {
|
||||
return prefixes[i].IPVersion < prefixes[j].IPVersion
|
||||
}
|
||||
// Then by prefix
|
||||
return prefixes[i].Prefix < prefixes[j].Prefix
|
||||
})
|
||||
|
||||
// Create enhanced prefixes with AS descriptions
|
||||
type EnhancedPrefix struct {
|
||||
database.LiveRoute
|
||||
OriginASDescription string
|
||||
Age string
|
||||
}
|
||||
|
||||
enhancedPrefixes := make([]EnhancedPrefix, len(prefixes))
|
||||
for i, prefix := range prefixes {
|
||||
enhancedPrefixes[i] = EnhancedPrefix{
|
||||
LiveRoute: prefix,
|
||||
Age: formatAge(prefix.LastUpdated),
|
||||
}
|
||||
|
||||
// Get AS description
|
||||
if asInfo, ok := asinfo.Get(prefix.OriginASN); ok {
|
||||
enhancedPrefixes[i].OriginASDescription = asInfo.Description
|
||||
}
|
||||
}
|
||||
|
||||
// Render template
|
||||
data := map[string]interface{}{
|
||||
"MaskLength": maskLength,
|
||||
"IPVersion": ipVersion,
|
||||
"Prefixes": enhancedPrefixes,
|
||||
"Count": len(prefixes),
|
||||
}
|
||||
|
||||
// Check if context is still valid before writing response
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
// Request was cancelled, don't write response
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
tmpl := templates.PrefixLengthTemplate()
|
||||
if err := tmpl.Execute(w, data); err != nil {
|
||||
s.logger.Error("Failed to render prefix length template", "error", err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handlePrefixLength6 shows a random sample of IPv6 prefixes with the specified mask length
|
||||
func (s *Server) handlePrefixLength6() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
lengthStr := chi.URLParam(r, "length")
|
||||
if lengthStr == "" {
|
||||
http.Error(w, "Length parameter is required", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
maskLength, err := strconv.Atoi(lengthStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid mask length", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Validate IPv6 mask length
|
||||
const maxIPv6MaskLength = 128
|
||||
if maskLength < 0 || maskLength > maxIPv6MaskLength {
|
||||
http.Error(w, "Invalid IPv6 mask length", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const ipVersion = 6
|
||||
|
||||
// Get random sample of prefixes
|
||||
const maxPrefixes = 500
|
||||
prefixes, err := s.db.GetRandomPrefixesByLengthContext(r.Context(), maskLength, ipVersion, maxPrefixes)
|
||||
|
@ -29,6 +29,7 @@ func (s *Server) setupRoutes() {
|
||||
r.Get("/as/{asn}", s.handleASDetail())
|
||||
r.Get("/prefix/{prefix}", s.handlePrefixDetail())
|
||||
r.Get("/prefixlength/{length}", s.handlePrefixLength())
|
||||
r.Get("/prefixlength6/{length}", s.handlePrefixLength6())
|
||||
r.Get("/ip/{ip}", s.handleIPRedirect())
|
||||
|
||||
// API routes
|
||||
|
@ -236,12 +236,16 @@
|
||||
// Sort by mask length
|
||||
distribution.sort((a, b) => a.mask_length - b.mask_length);
|
||||
|
||||
// Determine the URL path based on whether this is IPv4 or IPv6
|
||||
const isIPv6 = elementId.includes('ipv6');
|
||||
const urlPath = isIPv6 ? '/prefixlength6/' : '/prefixlength/';
|
||||
|
||||
distribution.forEach(item => {
|
||||
const metric = document.createElement('div');
|
||||
metric.className = 'metric';
|
||||
metric.innerHTML = `
|
||||
<span class="metric-label">/${item.mask_length}</span>
|
||||
<a href="/prefixlength/${item.mask_length}" class="metric-value metric-link">${formatNumber(item.count)}</a>
|
||||
<a href="${urlPath}${item.mask_length}" class="metric-value metric-link">${formatNumber(item.count)}</a>
|
||||
`;
|
||||
container.appendChild(metric);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user