refactored responses and http server

This commit is contained in:
Annika Hannig 2021-10-27 17:54:51 +00:00
parent aa9292b74c
commit 330047fac1
No known key found for this signature in database
GPG Key ID: 62E226E47DDCE58D
29 changed files with 324 additions and 215 deletions

View File

@ -8,7 +8,9 @@ import (
// A Response is a general API response. All API responses // A Response is a general API response. All API responses
// contain meta information with API version and caching // contain meta information with API version and caching
// information. // information.
type Response interface{} type Response struct {
Meta *Meta `json:"api"`
}
// Details are usually the original backend response // Details are usually the original backend response
type Details map[string]interface{} type Details map[string]interface{}
@ -101,8 +103,8 @@ type Status struct {
// StatusResponse ?? // StatusResponse ??
type StatusResponse struct { type StatusResponse struct {
Response
Status Status `json:"status"` Status Status `json:"status"`
Meta *Meta `json:"api"`
} }
// A RouteServer is a datasource with attributes. // A RouteServer is a datasource with attributes.

View File

@ -89,15 +89,15 @@ func (n *Neighbor) MatchName(name string) bool {
// A NeighborsResponse is a list of neighbors with // A NeighborsResponse is a list of neighbors with
// caching information. // caching information.
type NeighborsResponse struct { type NeighborsResponse struct {
Response
Neighbors Neighbors `json:"neighbors"` Neighbors Neighbors `json:"neighbors"`
Meta *Meta `json:"api"`
} }
// CacheTTL returns the duration of validity // CacheTTL returns the duration of validity
// of the neighbor response. // of the neighbor response.
func (res *NeighborsResponse) CacheTTL() time.Duration { func (res *NeighborsResponse) CacheTTL() time.Duration {
now := time.Now().UTC() now := time.Now().UTC()
return res.Meta.TTL.Sub(now) return res.Response.Meta.TTL.Sub(now)
} }
// NeighborsLookupResults is a mapping of lookup neighbors. // NeighborsLookupResults is a mapping of lookup neighbors.
@ -130,6 +130,6 @@ func (neighbors NeighborsStatus) Swap(i, j int) {
// NeighborsStatusResponse contains the status of all neighbors // NeighborsStatusResponse contains the status of all neighbors
// on a RS. // on a RS.
type NeighborsStatusResponse struct { type NeighborsStatusResponse struct {
Response
Neighbors NeighborsStatus `json:"neighbors"` Neighbors NeighborsStatus `json:"neighbors"`
Meta *Meta `json:"api"`
} }

View File

@ -69,7 +69,7 @@ func (routes Routes) Swap(i, j int) {
// RoutesResponse contains all routes from a source // RoutesResponse contains all routes from a source
type RoutesResponse struct { type RoutesResponse struct {
Meta *Meta `json:api` Response
Imported Routes `json:"imported"` Imported Routes `json:"imported"`
Filtered Routes `json:"filtered"` Filtered Routes `json:"filtered"`
NotExported Routes `json:"not_exported"` NotExported Routes `json:"not_exported"`
@ -78,11 +78,11 @@ type RoutesResponse struct {
// CacheTTL returns the cache ttl of the reponse // CacheTTL returns the cache ttl of the reponse
func (res *RoutesResponse) CacheTTL() time.Duration { func (res *RoutesResponse) CacheTTL() time.Duration {
now := time.Now().UTC() now := time.Now().UTC()
return res.Meta.TTL.Sub(now) return res.Response.Meta.TTL.Sub(now)
} }
// Timed responses include the duration of the request // TimedResponse include the duration of the request
type Timed struct { type TimedResponse struct {
RequestDuration float64 `json:"request_duration_ms"` RequestDuration float64 `json:"request_duration_ms"`
} }
@ -95,13 +95,13 @@ type Pagination struct {
TotalResults int `json:"total_results"` TotalResults int `json:"total_results"`
} }
// A Paginated response with pagination info // A PaginatedResponse with pagination info
type Paginated struct { type PaginatedResponse struct {
Pagination Pagination `json:"pagination"` Pagination Pagination `json:"pagination"`
} }
// Searchable responses include filters applied and available // FilteredResponse includes filters applied and available
type Searchable struct { type FilteredResponse struct {
FiltersAvailable *SearchFilters `json:"filters_available"` FiltersAvailable *SearchFilters `json:"filters_available"`
FiltersApplied *SearchFilters `json:"filters_applied"` FiltersApplied *SearchFilters `json:"filters_applied"`
} }
@ -157,33 +157,49 @@ func (r LookupRoutes) Swap(i, j int) {
r[i], r[j] = r[j], r[i] r[i], r[j] = r[j], r[i]
} }
// RoutesLookup contains routes and pagination info
type RoutesLookup struct {
Routes LookupRoutes `json:"routes"`
Pagination Pagination `json:"pagination"`
}
// RoutesLookupResponse is a PaginatedResponse with // RoutesLookupResponse is a PaginatedResponse with
// a set of lookup routes, as the result of a query of // a set of lookup routes, as the result of a query of
// a specific route server. // a specific route server.
type RoutesLookupResponse struct { type RoutesLookupResponse struct {
Paginated Response
Timed PaginatedResponse
Searchable TimedResponse
FilteredResponse
Routes LookupRoutes `json:"routes"` Routes LookupRoutes `json:"routes"`
Meta *Meta `json:"api"`
} }
// GlobalRoutesLookupResponse is the result of a routes // GlobalRoutesLookupResponse is the result of a routes
// query across all route servers. // query across all route servers.
type GlobalRoutesLookupResponse struct { type GlobalRoutesLookupResponse struct {
Response Response
Paginated PaginatedResponse
Timed TimedResponse
Searchable FilteredResponse
Routes LookupRoutes `json:"routes"` Routes LookupRoutes `json:"routes"`
} }
// A PaginatedRoutesResponse includes routes and pagination
// information form a single route server
type PaginatedRoutesResponse struct {
Response
PaginatedResponse
TimedResponse
FilteredResponse
RoutesResponse
}
// A PaginatedRoutesLookupResponse TODO // A PaginatedRoutesLookupResponse TODO
type PaginatedRoutesLookupResponse struct { type PaginatedRoutesLookupResponse struct {
Response Response
Timed TimedResponse
Searchable FilteredResponse
Imported *RoutesLookupResponse `json:"imported"` Imported *RoutesLookup `json:"imported"`
Filtered *RoutesLookupResponse `json:"filtered"` Filtered *RoutesLookup `json:"filtered"`
} }

View File

@ -10,11 +10,13 @@ func TestStatusResponseSerialization(t *testing.T) {
// Make status // Make status
response := StatusResponse{ response := StatusResponse{
Meta: &Meta{ Response: Response{
Version: "2.0.0", Meta: &Meta{
CacheStatus: CacheStatus{}, Version: "2.0.0",
ResultFromCache: false, CacheStatus: CacheStatus{},
TTL: time.Now(), ResultFromCache: false,
TTL: time.Now(),
},
}, },
Status: Status{ Status: Status{
Message: "Server is up and running", Message: "Server is up and running",

View File

@ -8,9 +8,6 @@ import (
"strings" "strings"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/alice-lg/alice-lg/pkg/api"
"github.com/alice-lg/alice-lg/pkg/config"
) )
// Alice LG Rest API // Alice LG Rest API
@ -33,7 +30,9 @@ import (
// LookupPrefix /api/v1/lookup/prefix?q=<prefix> // LookupPrefix /api/v1/lookup/prefix?q=<prefix>
// LookupNeighbor /api/v1/lookup/neighbor?asn=1235 // LookupNeighbor /api/v1/lookup/neighbor?asn=1235
type apiEndpoint func(*http.Request, httprouter.Params) (api.Response, error) type response interface{}
type apiEndpoint func(*http.Request, httprouter.Params) (response, error)
// Wrap handler for access controll, throtteling and compression // Wrap handler for access controll, throtteling and compression
func endpoint(wrapped apiEndpoint) httprouter.Handle { func endpoint(wrapped apiEndpoint) httprouter.Handle {
@ -86,7 +85,6 @@ func endpoint(wrapped apiEndpoint) httprouter.Handle {
// Register api endpoints // Register api endpoints
func (s *Server) apiRegisterEndpoints( func (s *Server) apiRegisterEndpoints(
cfg *config.Config,
router *httprouter.Router, router *httprouter.Router,
) error { ) error {
@ -111,7 +109,7 @@ func (s *Server) apiRegisterEndpoints(
endpoint(s.apiRoutesListNotExported)) endpoint(s.apiRoutesListNotExported))
// Querying // Querying
if cfg.Server.EnablePrefixLookup == true { if s.cfg.Server.EnablePrefixLookup == true {
router.GET("/api/v1/lookup/prefix", router.GET("/api/v1/lookup/prefix",
endpoint(s.apiLookupPrefixGlobal)) endpoint(s.apiLookupPrefixGlobal))
router.GET("/api/v1/lookup/neighbors", router.GET("/api/v1/lookup/neighbors",

View File

@ -13,7 +13,7 @@ import (
func (s *Server) apiStatusShow( func (s *Server) apiStatusShow(
_req *http.Request, _req *http.Request,
_params httprouter.Params, _params httprouter.Params,
) (api.Response, error) { ) (response, error) {
status, err := CollectAppStatus(s.routesStore, s.neighborsStore) status, err := CollectAppStatus(s.routesStore, s.neighborsStore)
return status, err return status, err
} }
@ -22,7 +22,7 @@ func (s *Server) apiStatusShow(
func (s *Server) apiStatus( func (s *Server) apiStatus(
_req *http.Request, _req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
rsID, err := validateSourceID(params.ByName("id")) rsID, err := validateSourceID(params.ByName("id"))
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,7 +35,7 @@ func (s *Server) apiStatus(
result, err := source.Status() result, err := source.Status()
if err != nil { if err != nil {
apiLogSourceError("status", rsID, err) s.logSourceError("status", rsID, err)
} }
return result, err return result, err
@ -45,7 +45,7 @@ func (s *Server) apiStatus(
func (s *Server) apiConfigShow( func (s *Server) apiConfigShow(
_req *http.Request, _req *http.Request,
_params httprouter.Params, _params httprouter.Params,
) (api.Response, error) { ) (response, error) {
result := api.ConfigResponse{ result := api.ConfigResponse{
Asn: s.cfg.Server.Asn, Asn: s.cfg.Server.Asn,
BGPCommunities: s.cfg.UI.BGPCommunities, BGPCommunities: s.cfg.UI.BGPCommunities,

View File

@ -15,7 +15,7 @@ import (
func (s *Server) apiNeighborsList( func (s *Server) apiNeighborsList(
_req *http.Request, _req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
rsID, err := validateSourceID(params.ByName("id")) rsID, err := validateSourceID(params.ByName("id"))
if err != nil { if err != nil {
return nil, err return nil, err
@ -30,26 +30,28 @@ func (s *Server) apiNeighborsList(
neighbors := s.neighborsStore.GetNeighborsAt(rsID) neighbors := s.neighborsStore.GetNeighborsAt(rsID)
// Make response // Make response
neighborsResponse = &api.NeighborsResponse{ neighborsResponse = &api.NeighborsResponse{
Meta: &api.Meta{ Response: api.Response{
Version: config.Version, Meta: &api.Meta{
CacheStatus: api.CacheStatus{ Version: config.Version,
OrigTTL: 0, CacheStatus: api.CacheStatus{
CachedAt: sourceStatus.LastRefresh, OrigTTL: 0,
CachedAt: sourceStatus.LastRefresh,
},
ResultFromCache: true, // you bet!
TTL: sourceStatus.LastRefresh.Add(
s.neighborsStore.RefreshInterval),
}, },
ResultFromCache: true, // you bet!
TTL: sourceStatus.LastRefresh.Add(
s.neighborsStore.RefreshInterval),
}, },
Neighbors: neighbors, Neighbors: neighbors,
} }
} else { } else {
source := s.neighborsStore.SourceInstanceByID(rsID) source := s.cfg.SourceInstanceByID(rsID)
if source == nil { if source == nil {
return nil, ErrSourceNotFound return nil, ErrSourceNotFound
} }
neighborsResponse, err = source.Neighbors() neighborsResponse, err = source.Neighbors()
if err != nil { if err != nil {
apiLogSourceError("neighbors", rsID, err) s.logSourceError("neighbors", rsID, err)
return nil, err return nil, err
} }
} }

View File

@ -13,7 +13,7 @@ import (
func (s *Server) apiRoutesList( func (s *Server) apiRoutesList(
_req *http.Request, _req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
rsID, err := validateSourceID(params.ByName("id")) rsID, err := validateSourceID(params.ByName("id"))
if err != nil { if err != nil {
return nil, err return nil, err
@ -27,7 +27,7 @@ func (s *Server) apiRoutesList(
result, err := source.Routes(neighborID) result, err := source.Routes(neighborID)
if err != nil { if err != nil {
apiLogSourceError("routes", rsID, neighborID, err) s.logSourceError("routes", rsID, neighborID, err)
} }
return result, err return result, err
@ -37,7 +37,7 @@ func (s *Server) apiRoutesList(
func (s *Server) apiRoutesListReceived( func (s *Server) apiRoutesListReceived(
req *http.Request, req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
// Measure response time // Measure response time
t0 := time.Now() t0 := time.Now()
@ -54,7 +54,7 @@ func (s *Server) apiRoutesListReceived(
result, err := source.RoutesReceived(neighborID) result, err := source.RoutesReceived(neighborID)
if err != nil { if err != nil {
apiLogSourceError("routes_received", rsID, neighborID, err) s.logSourceError("routes_received", rsID, neighborID, err)
return nil, err return nil, err
} }
@ -91,18 +91,22 @@ func (s *Server) apiRoutesListReceived(
// Make paginated response // Make paginated response
response := api.PaginatedRoutesResponse{ response := api.PaginatedRoutesResponse{
RoutesResponse: &api.RoutesResponse{ RoutesResponse: api.RoutesResponse{
Api: result.Api, Response: api.Response{
Meta: result.Response.Meta,
},
Imported: routes, Imported: routes,
}, },
TimedResponse: api.TimedResponse{ TimedResponse: api.TimedResponse{
RequestDuration: DurationMs(queryDuration), RequestDuration: DurationMs(queryDuration),
}, },
FilterableResponse: api.FilterableResponse{ FilteredResponse: api.FilteredResponse{
FiltersAvailable: filtersAvailable, FiltersAvailable: filtersAvailable,
FiltersApplied: filtersApplied, FiltersApplied: filtersApplied,
}, },
Pagination: pagination, PaginatedResponse: api.PaginatedResponse{
Pagination: pagination,
},
} }
return response, nil return response, nil
@ -111,7 +115,7 @@ func (s *Server) apiRoutesListReceived(
func (s *Server) apiRoutesListFiltered( func (s *Server) apiRoutesListFiltered(
req *http.Request, req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
t0 := time.Now() t0 := time.Now()
rsID, err := validateSourceID(params.ByName("id")) rsID, err := validateSourceID(params.ByName("id"))
@ -127,7 +131,7 @@ func (s *Server) apiRoutesListFiltered(
result, err := source.RoutesFiltered(neighborID) result, err := source.RoutesFiltered(neighborID)
if err != nil { if err != nil {
apiLogSourceError("routes_filtered", rsID, neighborID, err) s.logSourceError("routes_filtered", rsID, neighborID, err)
return nil, err return nil, err
} }
@ -164,18 +168,22 @@ func (s *Server) apiRoutesListFiltered(
// Make response // Make response
response := api.PaginatedRoutesResponse{ response := api.PaginatedRoutesResponse{
RoutesResponse: &api.RoutesResponse{ RoutesResponse: api.RoutesResponse{
Api: result.Api, Response: api.Response{
Meta: result.Response.Meta,
},
Filtered: routes, Filtered: routes,
}, },
TimedResponse: api.TimedResponse{ TimedResponse: api.TimedResponse{
RequestDuration: DurationMs(queryDuration), RequestDuration: DurationMs(queryDuration),
}, },
FilterableResponse: api.FilterableResponse{ FilteredResponse: api.FilteredResponse{
FiltersAvailable: filtersAvailable, FiltersAvailable: filtersAvailable,
FiltersApplied: filtersApplied, FiltersApplied: filtersApplied,
}, },
Pagination: pagination, PaginatedResponse: api.PaginatedResponse{
Pagination: pagination,
},
} }
return response, nil return response, nil
@ -184,7 +192,7 @@ func (s *Server) apiRoutesListFiltered(
func (s *Server) apiRoutesListNotExported( func (s *Server) apiRoutesListNotExported(
req *http.Request, req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
t0 := time.Now() t0 := time.Now()
rsID, err := validateSourceID(params.ByName("id")) rsID, err := validateSourceID(params.ByName("id"))
@ -200,7 +208,7 @@ func (s *Server) apiRoutesListNotExported(
result, err := source.RoutesNotExported(neighborID) result, err := source.RoutesNotExported(neighborID)
if err != nil { if err != nil {
apiLogSourceError("routes_not_exported", rsID, neighborID, err) s.logSourceError("routes_not_exported", rsID, neighborID, err)
return nil, err return nil, err
} }
@ -237,18 +245,22 @@ func (s *Server) apiRoutesListNotExported(
// Make response // Make response
response := api.PaginatedRoutesResponse{ response := api.PaginatedRoutesResponse{
RoutesResponse: &api.RoutesResponse{ RoutesResponse: api.RoutesResponse{
Api: result.Api, Response: api.Response{
Meta: result.Response.Meta,
},
NotExported: routes, NotExported: routes,
}, },
TimedResponse: api.TimedResponse{ TimedResponse: api.TimedResponse{
RequestDuration: DurationMs(queryDuration), RequestDuration: DurationMs(queryDuration),
}, },
FilterableResponse: api.FilterableResponse{ FilteredResponse: api.FilteredResponse{
FiltersAvailable: filtersAvailable, FiltersAvailable: filtersAvailable,
FiltersApplied: filtersApplied, FiltersApplied: filtersApplied,
}, },
Pagination: pagination, PaginatedResponse: api.PaginatedResponse{
Pagination: pagination,
},
} }
return response, nil return response, nil

View File

@ -13,14 +13,14 @@ import (
func (s *Server) apiRouteServersList( func (s *Server) apiRouteServersList(
_req *http.Request, _req *http.Request,
_params httprouter.Params, _params httprouter.Params,
) (api.Response, error) { ) (response, error) {
// Get list of sources from config, // Get list of sources from config,
routeservers := api.RouteServers{} routeservers := api.RouteServers{}
sources := s.cfg.Sources sources := s.cfg.Sources
for _, source := range sources { for _, source := range sources {
routeservers = append(routeservers, api.RouteServer{ routeservers = append(routeservers, api.RouteServer{
Id: source.ID, ID: source.ID,
Type: source.Type, Type: source.Type,
Name: source.Name, Name: source.Name,
Group: source.Group, Group: source.Group,

View File

@ -15,7 +15,7 @@ import (
func (s *Server) apiLookupPrefixGlobal( func (s *Server) apiLookupPrefixGlobal(
req *http.Request, req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
// TODO: This function is way too long // TODO: This function is way too long
// Get prefix to query // Get prefix to query
@ -106,29 +106,27 @@ func (s *Server) apiLookupPrefixGlobal(
// Make response // Make response
response := api.PaginatedRoutesLookupResponse{ response := api.PaginatedRoutesLookupResponse{
Api: api.ApiStatus{ Response: api.Response{
CacheStatus: api.CacheStatus{ Meta: &api.Meta{
CachedAt: AliceRoutesStore.CachedAt(), CacheStatus: api.CacheStatus{
CachedAt: s.routesStore.CachedAt(),
},
ResultFromCache: true, // Well.
TTL: s.routesStore.CacheTTL(),
}, },
ResultFromCache: true, // Well.
Ttl: AliceRoutesStore.CacheTTL(),
}, },
TimedResponse: api.TimedResponse{ TimedResponse: api.TimedResponse{
RequestDuration: DurationMs(queryDuration), RequestDuration: DurationMs(queryDuration),
}, },
Imported: &api.LookupRoutesResponse{ Imported: &api.RoutesLookup{
Routes: routesImported, Routes: routesImported,
PaginatedResponse: &api.PaginatedResponse{ Pagination: paginationImported,
Pagination: paginationImported,
},
}, },
Filtered: &api.LookupRoutesResponse{ Filtered: &api.RoutesLookup{
Routes: routesFiltered, Routes: routesFiltered,
PaginatedResponse: &api.PaginatedResponse{ Pagination: paginationFiltered,
Pagination: paginationFiltered,
},
}, },
FilterableResponse: api.FilterableResponse{ FilteredResponse: api.FilteredResponse{
FiltersAvailable: filtersAvailable, FiltersAvailable: filtersAvailable,
FiltersApplied: filtersApplied, FiltersApplied: filtersApplied,
}, },
@ -140,7 +138,7 @@ func (s *Server) apiLookupPrefixGlobal(
func (s *Server) apiLookupNeighborsGlobal( func (s *Server) apiLookupNeighborsGlobal(
req *http.Request, req *http.Request,
params httprouter.Params, params httprouter.Params,
) (api.Response, error) { ) (response, error) {
// Query neighbors store // Query neighbors store
filter := api.NeighborFilterFromQuery(req.URL.Query()) filter := api.NeighborFilterFromQuery(req.URL.Query())
neighbors := s.neighborsStore.FilterNeighbors(filter) neighbors := s.neighborsStore.FilterNeighbors(filter)
@ -149,12 +147,14 @@ func (s *Server) apiLookupNeighborsGlobal(
// Make response // Make response
response := &api.NeighborsResponse{ response := &api.NeighborsResponse{
Api: api.ApiStatus{ Response: api.Response{
CacheStatus: api.CacheStatus{ Meta: &api.Meta{
CachedAt: s.neighborsStore.CachedAt(), CacheStatus: api.CacheStatus{
CachedAt: s.neighborsStore.CachedAt(),
},
ResultFromCache: true, // You would not have guessed.
TTL: s.neighborsStore.CacheTTL(),
}, },
ResultFromCache: true, // You would not have guessed.
Ttl: s.neighborsStore.CacheTTL(),
}, },
Neighbors: neighbors, Neighbors: neighbors,
} }

View File

@ -60,7 +60,7 @@ func apiErrorResponse(
status := StatusError status := StatusError
switch e := err.(type) { switch e := err.(type) {
case *ResourceNotFoundError: case *ErrResourceNotFoundError:
tag = TagResourceNotFound tag = TagResourceNotFound
code = CodeResourceNotFound code = CodeResourceNotFound
status = StatusResourceNotFound status = StatusResourceNotFound

View File

@ -1,25 +0,0 @@
package http
import (
"fmt"
"testing"
)
func TestApiLogSourceError(t *testing.T) {
err := fmt.Errorf("an unexpected error occured")
conf := &Config{
Sources: []*SourceConfig{
&SourceConfig{
ID: "rs1v4",
Name: "rs1.example.net (IPv4)",
},
},
}
AliceConfig = conf
apiLogSourceError("foo.bar", "rs1v4", 23, "Test")
apiLogSourceError("foo.bam", "rs1v4", err)
apiLogSourceError("foo.baz", "rs1v4", 23, 42, "foo", err)
}

View File

@ -8,16 +8,16 @@ import (
func TestApiRoutesPagination(t *testing.T) { func TestApiRoutesPagination(t *testing.T) {
routes := api.Routes{ routes := api.Routes{
&api.Route{Id: "r01"}, &api.Route{ID: "r01"},
&api.Route{Id: "r02"}, &api.Route{ID: "r02"},
&api.Route{Id: "r03"}, &api.Route{ID: "r03"},
&api.Route{Id: "r04"}, &api.Route{ID: "r04"},
&api.Route{Id: "r05"}, &api.Route{ID: "r05"},
&api.Route{Id: "r06"}, &api.Route{ID: "r06"},
&api.Route{Id: "r07"}, &api.Route{ID: "r07"},
&api.Route{Id: "r08"}, &api.Route{ID: "r08"},
&api.Route{Id: "r09"}, &api.Route{ID: "r09"},
&api.Route{Id: "r10"}, &api.Route{ID: "r10"},
} }
paginated, pagination := apiPaginateRoutes(routes, 0, 8) paginated, pagination := apiPaginateRoutes(routes, 0, 8)
@ -36,13 +36,13 @@ func TestApiRoutesPagination(t *testing.T) {
// Check paginated slicing // Check paginated slicing
r := paginated[0] r := paginated[0]
if r.Id != "r01" { if r.ID != "r01" {
t.Error("First route on page 0 should be r01, got:", r.Id) t.Error("First route on page 0 should be r01, got:", r.ID)
} }
r = paginated[len(paginated)-1] r = paginated[len(paginated)-1]
if r.Id != "r08" { if r.ID != "r08" {
t.Error("Last route should be r08, but got:", r.Id) t.Error("Last route should be r08, but got:", r.ID)
} }
// Second page // Second page
@ -52,13 +52,13 @@ func TestApiRoutesPagination(t *testing.T) {
} }
r = paginated[0] r = paginated[0]
if r.Id != "r09" { if r.ID != "r09" {
t.Error("First route on page 1 should be r09, got:", r.Id) t.Error("First route on page 1 should be r09, got:", r.ID)
} }
r = paginated[len(paginated)-1] r = paginated[len(paginated)-1]
if r.Id != "r10" { if r.ID != "r10" {
t.Error("Last route should be r10, but got:", r.Id) t.Error("Last route should be r10, but got:", r.ID)
} }
// Access out of bound page // Access out of bound page

View File

@ -19,20 +19,20 @@ func makeQueryRequest(q string) *http.Request {
func makeQueryRoutes() api.Routes { func makeQueryRoutes() api.Routes {
routes := api.Routes{ routes := api.Routes{
&api.Route{ &api.Route{
Id: "route_01", ID: "route_01",
NeighborId: "n01", NeighborID: "n01",
Network: "123.42.43.0/24", Network: "123.42.43.0/24",
Gateway: "23.42.42.1", Gateway: "23.42.42.1",
}, },
&api.Route{ &api.Route{
Id: "route_02", ID: "route_02",
NeighborId: "n01", NeighborID: "n01",
Network: "142.23.0.0/16", Network: "142.23.0.0/16",
Gateway: "42.42.42.1", Gateway: "42.42.42.1",
}, },
&api.Route{ &api.Route{
Id: "route_03", ID: "route_03",
NeighborId: "n01", NeighborID: "n01",
Network: "123.43.0.0/16", Network: "123.43.0.0/16",
Gateway: "23.42.43.1", Gateway: "23.42.43.1",
}, },
@ -54,11 +54,11 @@ func TestApiQueryFilterNextHopGateway(t *testing.T) {
} }
// Check presence of route_01 and _03, matching prefix 123. // Check presence of route_01 and _03, matching prefix 123.
if filtered[0].Id != "route_01" { if filtered[0].ID != "route_01" {
t.Error("Expected route_01, got:", filtered[0].Id) t.Error("Expected route_01, got:", filtered[0].ID)
} }
if filtered[1].Id != "route_03" { if filtered[1].ID != "route_03" {
t.Error("Expected route_03, got:", filtered[1].Id) t.Error("Expected route_03, got:", filtered[1].ID)
} }
// Test another query matching the gateway only // Test another query matching the gateway only
@ -71,7 +71,7 @@ func TestApiQueryFilterNextHopGateway(t *testing.T) {
t.Error("Expected only one result") t.Error("Expected only one result")
} }
if filtered[0].Id != "route_02" { if filtered[0].ID != "route_02" {
t.Error("Expected route_02 to match criteria, got:", filtered[0]) t.Error("Expected route_02 to match criteria, got:", filtered[0])
} }
} }

View File

@ -7,12 +7,16 @@ import (
) )
// Log an api error // Log an api error
func apiLogSourceError(module string, sourceID string, params ...interface{}) { func (s *Server) logSourceError(
module string,
sourceID string,
params ...interface{},
) {
var err error var err error
args := []string{} args := []string{}
// Get source configuration // Get source configuration
source := AliceConfig.SourceByID(sourceID) source := s.cfg.SourceByID(sourceID)
sourceName := "unknown" sourceName := "unknown"
if source != nil { if source != nil {
sourceName = source.Name sourceName = source.Name

27
pkg/http/logging_test.go Normal file
View File

@ -0,0 +1,27 @@
package http
import (
"fmt"
"testing"
"github.com/alice-lg/alice-lg/pkg/config"
)
func TestApiLogSourceError(t *testing.T) {
err := fmt.Errorf("an unexpected error occured")
cfg := &config.Config{
Sources: []*config.SourceConfig{
&config.SourceConfig{
ID: "rs1v4",
Name: "rs1.example.net (IPv4)",
},
},
}
s := &Server{cfg: cfg}
s.logSourceError("foo.bar", "rs1v4", 23, "Test")
s.logSourceError("foo.bam", "rs1v4", err)
s.logSourceError("foo.baz", "rs1v4", 23, 42, "foo", err)
}

View File

@ -47,5 +47,5 @@ func (s *Server) Start() {
} }
// Start http server // Start http server
log.Fatal(http.ListenAndServe(cfg.Server.Listen, router)) log.Fatal(http.ListenAndServe(s.cfg.Server.Listen, router))
} }

View File

@ -9,8 +9,8 @@ import (
// AppStatus contains application status information // AppStatus contains application status information
type AppStatus struct { type AppStatus struct {
Version string `json:"version"` Version string `json:"version"`
Routes api.RoutesStoreStats `json:"routes"` Routes *api.RoutesStoreStats `json:"routes"`
Neighbors api.NeighborsStoreStats `json:"neighbors"` Neighbors *api.NeighborsStoreStats `json:"neighbors"`
} }
// CollectAppStatus initializes the application // CollectAppStatus initializes the application

View File

@ -25,21 +25,21 @@ import (
"path/filepath" "path/filepath"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/alice-lg/alice-lg/pkg/config"
) )
// Theme is a client customization through additional // Theme is a client customization through additional
// HTML, CSS and JS content. // HTML, CSS and JS content.
type Theme struct { type Theme struct {
Config ThemeConfig Config config.ThemeConfig
} }
// NewTheme creates a theme from a config // NewTheme creates a theme from a config
func NewTheme(config ThemeConfig) *Theme { func NewTheme(config config.ThemeConfig) *Theme {
theme := &Theme{ return &Theme{
Config: config, Config: config,
} }
return theme
} }
// Get includable files from theme directory // Get includable files from theme directory

View File

@ -7,6 +7,8 @@ import (
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/alice-lg/alice-lg/pkg/config"
) )
func touchFile(path, filename string) error { func touchFile(path, filename string) error {
@ -27,7 +29,7 @@ func TestThemeFiles(t *testing.T) {
touchFile(themePath, "script.js") touchFile(themePath, "script.js")
// Load theme // Load theme
theme := NewTheme(ThemeConfig{ theme := NewTheme(config.ThemeConfig{
BasePath: "/theme", BasePath: "/theme",
Path: themePath, Path: themePath,
}) })
@ -64,7 +66,7 @@ func TestThemeIncludeHash(t *testing.T) {
// Create some "stylesheets" and a "script" // Create some "stylesheets" and a "script"
touchFile(themePath, "style.css") touchFile(themePath, "style.css")
theme := NewTheme(ThemeConfig{ theme := NewTheme(config.ThemeConfig{
BasePath: "/theme", BasePath: "/theme",
Path: themePath, Path: themePath,
}) })
@ -91,28 +93,28 @@ func TestThemeIncludes(t *testing.T) {
touchFile(themePath, "script.js") touchFile(themePath, "script.js")
// Load theme // Load theme
theme := NewTheme(ThemeConfig{ theme := NewTheme(config.ThemeConfig{
BasePath: "/theme", BasePath: "/theme",
Path: themePath, Path: themePath,
}) })
stylesHtml := theme.StylesheetIncludes() stylesHTML := theme.StylesheetIncludes()
scriptsHtml := theme.ScriptIncludes() scriptsHTML := theme.ScriptIncludes()
if !strings.HasPrefix(scriptsHtml, "<script") { if !strings.HasPrefix(scriptsHTML, "<script") {
t.Error("Script include should start with <script") t.Error("Script include should start with <script")
} }
if strings.Index(scriptsHtml, "script.js") == -1 { if strings.Index(scriptsHTML, "script.js") == -1 {
t.Error("Scripts include should contain script.js") t.Error("Scripts include should contain script.js")
} }
if !strings.HasPrefix(stylesHtml, "<link") { if !strings.HasPrefix(stylesHTML, "<link") {
t.Error("Stylesheet include should start with <link") t.Error("Stylesheet include should start with <link")
} }
if strings.Index(stylesHtml, "extra.css") == -1 { if strings.Index(stylesHTML, "extra.css") == -1 {
t.Error("Stylesheet include should contain extra.css") t.Error("Stylesheet include should contain extra.css")
} }
if strings.Index(stylesHtml, "script.js") != -1 { if strings.Index(stylesHTML, "script.js") != -1 {
t.Error("Stylesheet include should not contain script.js") t.Error("Stylesheet include should not contain script.js")
} }

10
pkg/http/timeconv.go Normal file
View File

@ -0,0 +1,10 @@
package http
import (
"time"
)
// DurationMs converts time.Duration to milliseconds
func DurationMs(d time.Duration) float64 {
return float64(d) / 1000.0 / 1000.0 // nano -> micro -> milli
}

12
pkg/http/timeconv_test.go Normal file
View File

@ -0,0 +1,12 @@
package http
import (
"testing"
"time"
)
func TestDurationMs(t *testing.T) {
if DurationMs(time.Second) != 1000 {
t.Error("duration ms should return the duration in milliseconds")
}
}

View File

@ -9,7 +9,6 @@ import (
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/alice-lg/alice-lg/client" "github.com/alice-lg/alice-lg/client"
"github.com/alice-lg/alice-lg/pkg/config"
) )
// Web Client // Web Client
@ -17,8 +16,8 @@ import (
// Prepare client HTML: // Prepare client HTML:
// Set paths and add version to assets. // Set paths and add version to assets.
func webPrepareClientHTML(html string) string { func (s*Server)webPrepareClientHTML(html string) string {
status, _ := NewAppStatus() status, _ := CollectAppStatus(s.routesStore, s.neighborsStore)
// Replace paths and tags // Replace paths and tags
rewriter := strings.NewReplacer( rewriter := strings.NewReplacer(
@ -35,7 +34,7 @@ func webPrepareClientHTML(html string) string {
// Register assets handler and index handler // Register assets handler and index handler
// at /static and / // at /static and /
func webRegisterAssets(cfg *config.Config, router *httprouter.Router) error { func (s *Server) webRegisterAssets(router *httprouter.Router) error {
log.Println("Preparing and installing assets") log.Println("Preparing and installing assets")
// Prepare client html: Rewrite paths // Prepare client html: Rewrite paths
@ -45,14 +44,14 @@ func webRegisterAssets(cfg *config.Config, router *httprouter.Router) error {
} }
indexHTML := string(indexHTMLData) // TODO: migrate to []byte indexHTML := string(indexHTMLData) // TODO: migrate to []byte
theme := NewTheme(cfg.UI.Theme) theme := NewTheme(s.cfg.UI.Theme)
err = theme.RegisterThemeAssets(router) err = theme.RegisterThemeAssets(router)
if err != nil { if err != nil {
log.Println("Warning:", err) log.Println("Warning:", err)
} }
// Update paths // Update paths
indexHTML = webPrepareClientHTML(indexHTML) indexHTML = s.webPrepareClientHTML(indexHTML)
// Register static assets // Register static assets
router.Handler("GET", "/static/*path", client.AssetsHTTPHandler("/static")) router.Handler("GET", "/static/*path", client.AssetsHTTPHandler("/static"))

View File

@ -247,7 +247,9 @@ func (b *GenericBirdwatcher) Status() (*api.StatusResponse, error) {
} }
response := &api.StatusResponse{ response := &api.StatusResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Status: birdStatus, Status: birdStatus,
} }
@ -272,7 +274,9 @@ func (b *GenericBirdwatcher) NeighborsStatus() (
} }
response := &api.NeighborsStatusResponse{ response := &api.NeighborsStatusResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Neighbors: neighbors, Neighbors: neighbors,
} }
return response, nil // dereference for now return response, nil // dereference for now
@ -317,7 +321,9 @@ func (b *GenericBirdwatcher) LookupPrefix(
// Make result // Make result
response := &api.RoutesLookupResponse{ response := &api.RoutesLookupResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Routes: results, Routes: results,
} }
return response, nil return response, nil

View File

@ -257,7 +257,9 @@ func (src *MultiTableBirdwatcher) fetchRequiredRoutes(
} }
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Imported: importedRoutes, Imported: importedRoutes,
Filtered: filteredRoutes, Filtered: filteredRoutes,
} }
@ -381,7 +383,9 @@ func (src *MultiTableBirdwatcher) Neighbors() (*api.NeighborsResponse, error) {
} }
response = &api.NeighborsResponse{ response = &api.NeighborsResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Neighbors: neighbors, Neighbors: neighbors,
} }
@ -410,7 +414,7 @@ func (src *MultiTableBirdwatcher) Routes(
return nil, err return nil, err
} }
response.Meta = required.Meta response.Response.Meta = required.Meta
response.Imported = required.Imported response.Imported = required.Imported
response.Filtered = required.Filtered response.Filtered = required.Filtered
response.NotExported = notExported response.NotExported = notExported
@ -427,7 +431,7 @@ func (src *MultiTableBirdwatcher) RoutesReceived(
// Check if we have a cache hit // Check if we have a cache hit
cachedRoutes := src.routesRequiredCache.Get(neighborID) cachedRoutes := src.routesRequiredCache.Get(neighborID)
if cachedRoutes != nil { if cachedRoutes != nil {
response.Meta = cachedRoutes.Meta response.Response.Meta = cachedRoutes.Response.Meta
response.Imported = cachedRoutes.Imported response.Imported = cachedRoutes.Imported
return response, nil return response, nil
} }
@ -487,7 +491,9 @@ func (src *MultiTableBirdwatcher) RoutesNotExported(
} }
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
NotExported: routes, NotExported: routes,
} }
@ -519,7 +525,9 @@ func (src *MultiTableBirdwatcher) AllRoutes() (*api.RoutesResponse, error) {
} }
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
} }
// Parse the routes // Parse the routes

View File

@ -134,7 +134,9 @@ func (src *SingleTableBirdwatcher) fetchRequiredRoutes(
} }
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Imported: importedRoutes, Imported: importedRoutes,
Filtered: filteredRoutes, Filtered: filteredRoutes,
} }
@ -172,7 +174,9 @@ func (src *SingleTableBirdwatcher) Neighbors() (*api.NeighborsResponse, error) {
} }
response = &api.NeighborsResponse{ response = &api.NeighborsResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
Neighbors: neighbors, Neighbors: neighbors,
} }
@ -279,7 +283,9 @@ func (src *SingleTableBirdwatcher) RoutesNotExported(
} }
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
NotExported: routes, NotExported: routes,
} }
@ -311,7 +317,9 @@ func (src *SingleTableBirdwatcher) AllRoutes() (*api.RoutesResponse, error) {
} }
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: apiStatus, Response: api.Response{
Meta: apiStatus,
},
} }
// Parse the routes // Parse the routes

View File

@ -111,7 +111,9 @@ func (src *BgplgdSource) makeResponseMeta() *api.Meta {
func (src *BgplgdSource) Status() (*api.StatusResponse, error) { func (src *BgplgdSource) Status() (*api.StatusResponse, error) {
// Make API request and read response. We do not cache the result. // Make API request and read response. We do not cache the result.
response := &api.StatusResponse{ response := &api.StatusResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Status: api.Status{ Status: api.Status{
Version: "openbgpd", Version: "openbgpd",
Message: "openbgpd up and running", Message: "openbgpd up and running",
@ -160,7 +162,9 @@ func (src *BgplgdSource) Neighbors() (*api.NeighborsResponse, error) {
} }
response = &api.NeighborsResponse{ response = &api.NeighborsResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Neighbors: nb, Neighbors: nb,
} }
src.neighborsCache.Set(response) src.neighborsCache.Set(response)
@ -193,7 +197,9 @@ func (src *BgplgdSource) NeighborsStatus() (*api.NeighborsStatusResponse, error)
} }
response := &api.NeighborsStatusResponse{ response := &api.NeighborsStatusResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Neighbors: nb, Neighbors: nb,
} }
return response, nil return response, nil
@ -235,7 +241,9 @@ func (src *BgplgdSource) Routes(neighborID string) (*api.RoutesResponse, error)
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,
@ -279,7 +287,9 @@ func (src *BgplgdSource) RoutesReceived(neighborID string) (*api.RoutesResponse,
received := filterReceivedRoutes(src.cfg.RejectCommunities, routes) received := filterReceivedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: api.Routes{}, Filtered: api.Routes{},
@ -323,7 +333,9 @@ func (src *BgplgdSource) RoutesFiltered(neighborID string) (*api.RoutesResponse,
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: api.Routes{}, Imported: api.Routes{},
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,
@ -337,7 +349,9 @@ func (src *BgplgdSource) RoutesFiltered(neighborID string) (*api.RoutesResponse,
// from the rs for a neighbor. // from the rs for a neighbor.
func (src *BgplgdSource) RoutesNotExported(neighborID string) (*api.RoutesResponse, error) { func (src *BgplgdSource) RoutesNotExported(neighborID string) (*api.RoutesResponse, error) {
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: api.Routes{}, Imported: api.Routes{},
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: api.Routes{}, Filtered: api.Routes{},
@ -374,7 +388,9 @@ func (src *BgplgdSource) AllRoutes() (*api.RoutesResponse, error) {
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,

View File

@ -137,7 +137,9 @@ func (src *StateServerSource) Status() (*api.StatusResponse, error) {
} }
status := decodeAPIStatus(body) status := decodeAPIStatus(body)
response := &api.StatusResponse{ response := &api.StatusResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Status: status, Status: status,
} }
return response, nil return response, nil
@ -148,7 +150,7 @@ func (src *StateServerSource) Neighbors() (*api.NeighborsResponse, error) {
// Query cache and see if we have a hit // Query cache and see if we have a hit
response := src.neighborsCache.Get() response := src.neighborsCache.Get()
if response != nil { if response != nil {
response.Meta.ResultFromCache = true response.Response.Meta.ResultFromCache = true
return response, nil return response, nil
} }
@ -183,7 +185,9 @@ func (src *StateServerSource) Neighbors() (*api.NeighborsResponse, error) {
} }
response = &api.NeighborsResponse{ response = &api.NeighborsResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Neighbors: nb, Neighbors: nb,
} }
src.neighborsCache.Set(response) src.neighborsCache.Set(response)
@ -216,7 +220,9 @@ func (src *StateServerSource) NeighborsStatus() (*api.NeighborsStatusResponse, e
} }
response := &api.NeighborsStatusResponse{ response := &api.NeighborsStatusResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Neighbors: nb, Neighbors: nb,
} }
return response, nil return response, nil
@ -227,7 +233,7 @@ func (src *StateServerSource) NeighborsStatus() (*api.NeighborsStatusResponse, e
func (src *StateServerSource) Routes(neighborID string) (*api.RoutesResponse, error) { func (src *StateServerSource) Routes(neighborID string) (*api.RoutesResponse, error) {
response := src.routesCache.Get(neighborID) response := src.routesCache.Get(neighborID)
if response != nil { if response != nil {
response.Meta.ResultFromCache = true response.Response.Meta.ResultFromCache = true
return response, nil return response, nil
} }
@ -258,7 +264,9 @@ func (src *StateServerSource) Routes(neighborID string) (*api.RoutesResponse, er
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,
@ -272,7 +280,7 @@ func (src *StateServerSource) Routes(neighborID string) (*api.RoutesResponse, er
func (src *StateServerSource) RoutesReceived(neighborID string) (*api.RoutesResponse, error) { func (src *StateServerSource) RoutesReceived(neighborID string) (*api.RoutesResponse, error) {
response := src.routesReceivedCache.Get(neighborID) response := src.routesReceivedCache.Get(neighborID)
if response != nil { if response != nil {
response.Meta.ResultFromCache = true response.Response.Meta.ResultFromCache = true
return response, nil return response, nil
} }
@ -300,7 +308,9 @@ func (src *StateServerSource) RoutesReceived(neighborID string) (*api.RoutesResp
received := filterReceivedRoutes(src.cfg.RejectCommunities, routes) received := filterReceivedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: api.Routes{}, Filtered: api.Routes{},
@ -314,7 +324,7 @@ func (src *StateServerSource) RoutesReceived(neighborID string) (*api.RoutesResp
func (src *StateServerSource) RoutesFiltered(neighborID string) (*api.RoutesResponse, error) { func (src *StateServerSource) RoutesFiltered(neighborID string) (*api.RoutesResponse, error) {
response := src.routesFilteredCache.Get(neighborID) response := src.routesFilteredCache.Get(neighborID)
if response != nil { if response != nil {
response.Meta.ResultFromCache = true response.Response.Meta.ResultFromCache = true
return response, nil return response, nil
} }
@ -342,7 +352,9 @@ func (src *StateServerSource) RoutesFiltered(neighborID string) (*api.RoutesResp
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response = &api.RoutesResponse{ response = &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: api.Routes{}, Imported: api.Routes{},
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,
@ -356,7 +368,9 @@ func (src *StateServerSource) RoutesFiltered(neighborID string) (*api.RoutesResp
// from the rs for a neighbor. // from the rs for a neighbor.
func (src *StateServerSource) RoutesNotExported(neighborID string) (*api.RoutesResponse, error) { func (src *StateServerSource) RoutesNotExported(neighborID string) (*api.RoutesResponse, error) {
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: api.Routes{}, Imported: api.Routes{},
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: api.Routes{}, Filtered: api.Routes{},
@ -393,7 +407,9 @@ func (src *StateServerSource) AllRoutes() (*api.RoutesResponse, error) {
rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes) rejected := filterRejectedRoutes(src.cfg.RejectCommunities, routes)
response := &api.RoutesResponse{ response := &api.RoutesResponse{
Meta: src.makeResponseMeta(), Response: api.Response{
Meta: src.makeResponseMeta(),
},
Imported: received, Imported: received,
NotExported: api.Routes{}, NotExported: api.Routes{},
Filtered: rejected, Filtered: rejected,

View File

@ -4,7 +4,6 @@ package store
import ( import (
"strconv" "strconv"
"strings" "strings"
"time"
) )
// ContainsCi is like `strings.Contains` but case insensitive // ContainsCi is like `strings.Contains` but case insensitive
@ -39,8 +38,3 @@ func SerializeReasons(reasons map[int]string) map[string]string {
} }
return res return res
} }
// DurationMs converts time.Duration to milliseconds
func DurationMs(d time.Duration) float64 {
return float64(d) / 1000.0 / 1000.0 // nano -> micro -> milli
}