diff --git a/web/api/v1/api.go b/web/api/v1/api.go index d0deaba80..2e5e171d2 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -54,15 +54,6 @@ type response struct { Error string `json:"error,omitempty"` } -// API can register a set of endpoints in a router and handle -// them using the provided storage and query engine. -type API struct { - Storage local.Storage - QueryEngine *promql.Engine - - context func(r *http.Request) context.Context -} - // Enables cross-site script calls. func setCORS(w http.ResponseWriter) { w.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Origin") @@ -73,12 +64,28 @@ func setCORS(w http.ResponseWriter) { type apiFunc func(r *http.Request) (interface{}, *apiError) +// API can register a set of endpoints in a router and handle +// them using the provided storage and query engine. +type API struct { + Storage local.Storage + QueryEngine *promql.Engine + + context func(r *http.Request) context.Context + now func() model.Time +} + +// NewAPI returns an initialized API type. +func NewAPI(qe *promql.Engine, st local.Storage) *API { + return &API{ + QueryEngine: qe, + Storage: st, + context: route.Context, + now: model.Now, + } +} + // Register the API's endpoints in the given router. func (api *API) Register(r *route.Router) { - if api.context == nil { - api.context = route.Context - } - instr := func(name string, f apiFunc) http.HandlerFunc { hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { setCORS(w) @@ -108,10 +115,17 @@ type queryData struct { } func (api *API) query(r *http.Request) (interface{}, *apiError) { - ts, err := parseTime(r.FormValue("time")) - if err != nil { - return nil, &apiError{errorBadData, err} + var ts model.Time + if t := r.FormValue("time"); t != "" { + var err error + ts, err = parseTime(t) + if err != nil { + return nil, &apiError{errorBadData, err} + } + } else { + ts = api.now() } + qry, err := api.QueryEngine.NewInstantQuery(r.FormValue("query"), ts) if err != nil { return nil, &apiError{errorBadData, err} diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index cc51210ca..87053c487 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -35,9 +35,11 @@ func TestEndpoints(t *testing.T) { t.Fatal(err) } + now := model.Now() api := &API{ Storage: suite.Storage(), QueryEngine: suite.QueryEngine(), + now: func() model.Time { return now }, } start := model.Time(0) @@ -90,6 +92,19 @@ func TestEndpoints(t *testing.T) { }, }, }, + { + endpoint: api.query, + query: url.Values{ + "query": []string{"0.333"}, + }, + response: &queryData{ + ResultType: model.ValScalar, + Result: &model.Scalar{ + Value: 0.333, + Timestamp: now, + }, + }, + }, { endpoint: api.queryRange, query: url.Values{ @@ -140,14 +155,6 @@ func TestEndpoints(t *testing.T) { }, errType: errorBadData, }, - // Missing evaluation time. - { - endpoint: api.query, - query: url.Values{ - "query": []string{"0.333"}, - }, - errType: errorBadData, - }, // Bad query expression. { endpoint: api.query, diff --git a/web/web.go b/web/web.go index 135718d9a..bfcbdb639 100644 --- a/web/web.go +++ b/web/web.go @@ -138,10 +138,7 @@ func New(st local.Storage, qe *promql.Engine, rm *rules.Manager, status *Prometh queryEngine: qe, storage: st, - apiV1: &v1.API{ - QueryEngine: qe, - Storage: st, - }, + apiV1: v1.NewAPI(qe, st), apiLegacy: &legacy.API{ QueryEngine: qe, Storage: st,