alice-lg/pkg/http/api_endpoints_search.go

237 lines
5.8 KiB
Go
Raw Normal View History

2021-10-22 22:40:03 +02:00
package http
2018-09-22 15:51:20 +02:00
import (
2022-06-15 15:49:45 +02:00
"context"
2018-09-22 15:51:20 +02:00
"net/http"
2018-09-24 22:36:23 +02:00
"sort"
2018-09-22 15:51:20 +02:00
"time"
2021-03-22 16:50:08 +01:00
"github.com/julienschmidt/httprouter"
"github.com/alice-lg/alice-lg/pkg/api"
2021-10-27 14:48:52 +00:00
"github.com/alice-lg/alice-lg/pkg/decoders"
2018-09-22 15:51:20 +02:00
)
// Handle global lookup
2021-10-26 23:11:42 +02:00
func (s *Server) apiLookupPrefixGlobal(
2022-06-15 15:49:45 +02:00
ctx context.Context,
2018-09-24 22:29:13 +02:00
req *http.Request,
params httprouter.Params,
2021-10-27 17:54:51 +00:00
) (response, error) {
2019-10-07 18:13:08 +02:00
// TODO: This function is way too long
2022-07-27 18:00:31 +02:00
statusMeta := &api.StoreStatusMeta{
Neighbors: s.neighborsStore.Status(ctx),
Routes: s.routesStore.Status(ctx),
}
2018-09-24 22:29:13 +02:00
2018-09-22 15:51:20 +02:00
// Get prefix to query
q, err := validateQueryString(req, "q")
if err != nil {
return nil, err
}
2018-09-22 15:51:20 +02:00
q, filterTokens := QueryString(q).ExtractFilters()
2018-09-22 15:51:20 +02:00
// Get filters from query string
queryFilters, err := api.FiltersFromTokens(filterTokens)
if err != nil {
return nil, &ErrValidationFailed{
Param: "q",
Reason: err.Error(),
}
}
2018-09-22 15:51:20 +02:00
2018-10-15 10:55:27 +02:00
// Get additional filter criteria
filtersApplied, err := api.FiltersFromQuery(req.URL.Query())
2018-10-17 15:57:20 +02:00
if err != nil {
return nil, err
}
2018-10-15 10:55:27 +02:00
// Merge query filters into applied filters
filtersApplied = filtersApplied.Combine(queryFilters)
2024-01-26 14:19:18 +01:00
// Select the query strategy:
// Prefix -> fetch prefix
// _ -> fetch neighbors and routes
2024-01-26 14:19:18 +01:00
//
lookupPrefix := decoders.MaybePrefix(q)
2024-01-26 14:19:18 +01:00
lookupEmptyQuery := false
if q == "" && (filtersApplied.HasGroup(api.SearchKeyCommunities) ||
filtersApplied.HasGroup(api.SearchKeyExtCommunities) ||
filtersApplied.HasGroup(api.SearchKeyLargeCommunities)) {
lookupPrefix = true
lookupEmptyQuery = true
}
// Measure response time
t0 := time.Now()
2024-01-16 16:51:39 +01:00
2018-09-22 15:51:20 +02:00
// Perform query
var routes api.LookupRoutes
if lookupPrefix {
2024-01-26 14:19:18 +01:00
if !lookupEmptyQuery {
q, err = validatePrefixQuery(q)
if err != nil {
return nil, err
}
}
2024-01-16 16:33:22 +01:00
routes, err = s.routesStore.LookupPrefix(ctx, q, filtersApplied)
2021-12-06 10:03:17 +01:00
if err != nil {
return nil, err
}
2018-09-22 15:51:20 +02:00
} else {
// Query by neighbors
q, err = validateNeighborsQuery(q)
if err != nil {
return nil, err
}
2021-12-06 10:03:17 +01:00
neighbors, err := s.neighborsStore.LookupNeighbors(ctx, q)
if err != nil {
return nil, err
}
2024-01-16 16:33:22 +01:00
routes, err = s.routesStore.LookupPrefixForNeighbors(ctx, neighbors, filtersApplied)
2021-12-06 10:03:17 +01:00
if err != nil {
return nil, err
}
2018-09-22 15:51:20 +02:00
}
2018-09-24 22:29:13 +02:00
// Split routes
// TODO: Refactor at neighbors store
totalResults := len(routes)
imported := make(api.LookupRoutes, 0, totalResults)
filtered := make(api.LookupRoutes, 0, totalResults)
2024-01-15 11:16:13 +01:00
// Check if we should calculate community filter
// cardinalities.
filterCutoff := s.cfg.Server.PrefixLookupCommunityFilterCutoff
canFilterCommunities := totalResults <= filterCutoff
// In case there is a source filter applied, we can filter communities
if filtersApplied.HasGroup(api.SearchKeySources) {
canFilterCommunities = true
}
filtersNotAvailable := []string{}
if !canFilterCommunities {
2024-01-15 11:16:13 +01:00
filtersNotAvailable = append(
filtersNotAvailable, api.SearchKeyCommunities)
}
2024-01-16 16:33:22 +01:00
// Now, as we have allocated even more space split routes,
// and update the available filters...
2018-10-17 10:44:38 +02:00
filtersAvailable := api.NewSearchFilters()
2018-09-24 22:29:13 +02:00
for _, r := range routes {
2018-10-17 15:57:20 +02:00
2018-09-24 22:29:13 +02:00
switch r.State {
2021-12-06 10:03:17 +01:00
case api.RouteStateFiltered:
2018-09-24 22:29:13 +02:00
filtered = append(filtered, r)
2021-12-06 10:03:17 +01:00
case api.RouteStateImported:
2018-09-24 22:29:13 +02:00
imported = append(imported, r)
}
2018-10-17 10:44:38 +02:00
// Update available filters for sources and asns,
// conditionally for communities.
filtersAvailable.UpdateSourcesFromLookupRoute(r)
filtersAvailable.UpdateASNSFromLookupRoute(r)
if canFilterCommunities {
filtersAvailable.UpdateCommunitiesFromLookupRoute(r)
}
2018-09-22 15:51:20 +02:00
}
// Remove applied filters from available
filtersApplied.MergeProperties(filtersAvailable)
filtersAvailable = filtersAvailable.Sub(filtersApplied)
2018-09-24 22:36:23 +02:00
// Homogenize results
sort.Sort(imported)
sort.Sort(filtered)
2018-09-24 22:29:13 +02:00
// Paginate results
pageImported := apiQueryMustInt(req, "page_imported", 0)
2021-10-26 23:11:42 +02:00
pageSizeImported := s.cfg.UI.Pagination.RoutesAcceptedPageSize
2018-09-24 22:29:13 +02:00
routesImported, paginationImported := apiPaginateLookupRoutes(
imported, pageImported, pageSizeImported,
)
2018-09-22 15:51:20 +02:00
2018-09-24 22:29:13 +02:00
pageFiltered := apiQueryMustInt(req, "page_filtered", 0)
2021-10-26 23:11:42 +02:00
pageSizeFiltered := s.cfg.UI.Pagination.RoutesFilteredPageSize
2018-09-24 22:29:13 +02:00
routesFiltered, paginationFiltered := apiPaginateLookupRoutes(
filtered, pageFiltered, pageSizeFiltered,
)
2018-09-25 21:47:30 +02:00
// Calculate query duration
2018-09-24 22:29:13 +02:00
queryDuration := time.Since(t0)
2018-09-22 15:51:20 +02:00
2021-12-07 19:11:11 +01:00
cachedAt := s.routesStore.CachedAt(ctx)
ttl := s.routesStore.CacheTTL(ctx)
2021-12-06 10:03:17 +01:00
2018-09-24 22:29:13 +02:00
// Make response
response := api.PaginatedRoutesLookupResponse{
2021-10-27 17:54:51 +00:00
Response: api.Response{
Meta: &api.Meta{
CacheStatus: api.CacheStatus{
2021-12-06 10:03:17 +01:00
CachedAt: cachedAt,
2021-10-27 17:54:51 +00:00
},
2022-07-27 18:00:31 +02:00
StoreStatus: statusMeta,
2021-10-27 17:54:51 +00:00
ResultFromCache: true, // Well.
2021-12-06 10:03:17 +01:00
TTL: ttl,
2018-09-25 21:26:11 +02:00
},
},
TimedResponse: api.TimedResponse{
2018-09-24 22:29:13 +02:00
RequestDuration: DurationMs(queryDuration),
},
2021-10-27 17:54:51 +00:00
Imported: &api.RoutesLookup{
Routes: routesImported,
Pagination: paginationImported,
2018-09-24 22:29:13 +02:00
},
2021-10-27 17:54:51 +00:00
Filtered: &api.RoutesLookup{
Routes: routesFiltered,
Pagination: paginationFiltered,
2018-09-24 22:29:13 +02:00
},
2021-10-27 17:54:51 +00:00
FilteredResponse: api.FilteredResponse{
FiltersAvailable: filtersAvailable,
FiltersNotAvailable: filtersNotAvailable,
FiltersApplied: filtersApplied,
2018-10-17 10:44:38 +02:00
},
2018-09-22 15:51:20 +02:00
}
return response, nil
}
2019-10-05 12:10:27 +02:00
2021-10-26 23:11:42 +02:00
func (s *Server) apiLookupNeighborsGlobal(
2022-06-15 15:49:45 +02:00
ctx context.Context,
2019-10-05 12:10:27 +02:00
req *http.Request,
params httprouter.Params,
2021-10-27 17:54:51 +00:00
) (response, error) {
2022-07-27 18:00:31 +02:00
statusMeta := &api.StoreStatusMeta{
Neighbors: s.neighborsStore.Status(ctx),
}
2019-10-07 18:29:25 +02:00
// Query neighbors store
filter := api.NeighborFilterFromQuery(req.URL.Query())
2021-12-07 19:11:11 +01:00
neighbors, err := s.neighborsStore.FilterNeighbors(ctx, filter)
if err != nil {
return nil, err
}
2019-10-07 18:29:25 +02:00
2019-10-07 23:22:01 +02:00
sort.Sort(neighbors)
2019-10-07 18:29:25 +02:00
// Make response
2021-10-15 21:24:24 +02:00
response := &api.NeighborsResponse{
2021-10-27 17:54:51 +00:00
Response: api.Response{
Meta: &api.Meta{
CacheStatus: api.CacheStatus{
2021-12-07 19:11:11 +01:00
CachedAt: s.neighborsStore.CachedAt(ctx),
2021-10-27 17:54:51 +00:00
},
2022-07-27 18:00:31 +02:00
StoreStatus: statusMeta,
2021-10-27 17:54:51 +00:00
ResultFromCache: true, // You would not have guessed.
2021-12-07 19:11:11 +01:00
TTL: s.neighborsStore.CacheTTL(ctx),
2019-10-07 18:29:25 +02:00
},
},
2021-10-15 21:24:24 +02:00
Neighbors: neighbors,
2019-10-07 18:29:25 +02:00
}
return response, nil
2019-10-05 12:10:27 +02:00
}