Refactor server package: split handlers and routes into separate files
- Move all handler functions to handlers.go - Move setupRoutes to routes.go - Clean up server.go to only contain core server logic - Add missing GetASDetails and GetPrefixDetails to mockStore for tests - Fix linter errors (magic numbers, unused parameters, blank lines)
This commit is contained in:
@@ -743,3 +743,101 @@ func CalculateIPv4Range(cidr string) (start, end uint32, err error) {
|
||||
|
||||
return start, end, nil
|
||||
}
|
||||
|
||||
// GetASDetails returns detailed information about an AS including prefixes
|
||||
func (d *Database) GetASDetails(asn int) (*ASN, []LiveRoute, error) {
|
||||
// Get AS information
|
||||
var asnInfo ASN
|
||||
var idStr string
|
||||
var handle, description sql.NullString
|
||||
err := d.db.QueryRow(
|
||||
"SELECT id, number, handle, description, first_seen, last_seen FROM asns WHERE number = ?",
|
||||
asn,
|
||||
).Scan(&idStr, &asnInfo.Number, &handle, &description, &asnInfo.FirstSeen, &asnInfo.LastSeen)
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil, fmt.Errorf("%w: AS%d", ErrNoRoute, asn)
|
||||
}
|
||||
|
||||
return nil, nil, fmt.Errorf("failed to query AS: %w", err)
|
||||
}
|
||||
|
||||
asnInfo.ID, _ = uuid.Parse(idStr)
|
||||
asnInfo.Handle = handle.String
|
||||
asnInfo.Description = description.String
|
||||
|
||||
// Get prefixes announced by this AS
|
||||
query := `
|
||||
SELECT DISTINCT prefix, mask_length, ip_version, last_updated
|
||||
FROM live_routes
|
||||
WHERE origin_asn = ?
|
||||
ORDER BY ip_version, mask_length, prefix
|
||||
`
|
||||
|
||||
rows, err := d.db.Query(query, asn)
|
||||
if err != nil {
|
||||
return &asnInfo, nil, fmt.Errorf("failed to query prefixes: %w", err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var prefixes []LiveRoute
|
||||
for rows.Next() {
|
||||
var route LiveRoute
|
||||
err := rows.Scan(&route.Prefix, &route.MaskLength, &route.IPVersion, &route.LastUpdated)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
route.OriginASN = asn
|
||||
prefixes = append(prefixes, route)
|
||||
}
|
||||
|
||||
return &asnInfo, prefixes, nil
|
||||
}
|
||||
|
||||
// GetPrefixDetails returns detailed information about a prefix
|
||||
func (d *Database) GetPrefixDetails(prefix string) ([]LiveRoute, error) {
|
||||
query := `
|
||||
SELECT lr.origin_asn, lr.peer_ip, lr.as_path, lr.next_hop, lr.last_updated,
|
||||
a.handle, a.description
|
||||
FROM live_routes lr
|
||||
LEFT JOIN asns a ON a.number = lr.origin_asn
|
||||
WHERE lr.prefix = ?
|
||||
ORDER BY lr.origin_asn, lr.peer_ip
|
||||
`
|
||||
|
||||
rows, err := d.db.Query(query, prefix)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query prefix details: %w", err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var routes []LiveRoute
|
||||
for rows.Next() {
|
||||
var route LiveRoute
|
||||
var pathJSON string
|
||||
var handle, description sql.NullString
|
||||
|
||||
err := rows.Scan(
|
||||
&route.OriginASN, &route.PeerIP, &pathJSON, &route.NextHop,
|
||||
&route.LastUpdated, &handle, &description,
|
||||
)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode AS path
|
||||
if err := json.Unmarshal([]byte(pathJSON), &route.ASPath); err != nil {
|
||||
route.ASPath = []int{}
|
||||
}
|
||||
|
||||
route.Prefix = prefix
|
||||
routes = append(routes, route)
|
||||
}
|
||||
|
||||
if len(routes) == 0 {
|
||||
return nil, fmt.Errorf("%w: %s", ErrNoRoute, prefix)
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ type Store interface {
|
||||
// IP lookup operations
|
||||
GetASInfoForIP(ip string) (*ASInfo, error)
|
||||
|
||||
// AS and prefix detail operations
|
||||
GetASDetails(asn int) (*ASN, []LiveRoute, error)
|
||||
GetPrefixDetails(prefix string) ([]LiveRoute, error)
|
||||
|
||||
// Lifecycle
|
||||
Close() error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user