refactored responses and http server
This commit is contained in:
parent
aa9292b74c
commit
330047fac1
@ -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.
|
||||||
|
@ -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"`
|
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
|
@ -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
|
||||||
|
@ -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])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
27
pkg/http/logging_test.go
Normal 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)
|
||||||
|
}
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
10
pkg/http/timeconv.go
Normal 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
12
pkg/http/timeconv_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
@ -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"))
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user