| 517 | } |
| 518 | |
| 519 | func (api *API) query(r *http.Request) (result apiFuncResult) { |
| 520 | limit, err := parseLimitParam(r.FormValue("limit")) |
| 521 | if err != nil { |
| 522 | return invalidParamError(err, "limit") |
| 523 | } |
| 524 | ts, err := parseTimeParam(r, "time", api.now()) |
| 525 | if err != nil { |
| 526 | return invalidParamError(err, "time") |
| 527 | } |
| 528 | ctx := r.Context() |
| 529 | if to := r.FormValue("timeout"); to != "" { |
| 530 | var cancel context.CancelFunc |
| 531 | timeout, err := parseDuration(to) |
| 532 | if err != nil { |
| 533 | return invalidParamError(err, "timeout") |
| 534 | } |
| 535 | |
| 536 | ctx, cancel = context.WithDeadline(ctx, api.now().Add(timeout)) |
| 537 | defer cancel() |
| 538 | } |
| 539 | |
| 540 | opts, err := extractQueryOpts(r) |
| 541 | if err != nil { |
| 542 | return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} |
| 543 | } |
| 544 | qry, err := api.QueryEngine.NewInstantQuery(ctx, api.Queryable, opts, r.FormValue("query"), ts) |
| 545 | if err != nil { |
| 546 | return invalidParamError(err, "query") |
| 547 | } |
| 548 | |
| 549 | // From now on, we must only return with a finalizer in the result (to |
| 550 | // be called by the caller) or call qry.Close ourselves (which is |
| 551 | // required in the case of a panic). |
| 552 | defer func() { |
| 553 | if result.finalizer == nil { |
| 554 | qry.Close() |
| 555 | } |
| 556 | }() |
| 557 | |
| 558 | ctx = httputil.ContextFromRequest(ctx, r) |
| 559 | |
| 560 | res := qry.Exec(ctx) |
| 561 | if res.Err != nil { |
| 562 | return apiFuncResult{nil, returnAPIError(res.Err), res.Warnings, qry.Close} |
| 563 | } |
| 564 | |
| 565 | warnings := res.Warnings |
| 566 | if limit > 0 { |
| 567 | var isTruncated bool |
| 568 | |
| 569 | res, isTruncated = truncateResults(res, limit) |
| 570 | if isTruncated { |
| 571 | warnings = warnings.Add(errors.New("results truncated due to limit")) |
| 572 | } |
| 573 | } |
| 574 | // Optional stats field in response if parameter "stats" is not empty. |
| 575 | sr := api.statsRenderer |
| 576 | if sr == nil { |