parent
36a7b45908
commit
b031e22003
|
@ -525,7 +525,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
$ref: "#/components/schemas/Error"
|
||||
/macros:
|
||||
get:
|
||||
tags:
|
||||
|
@ -2152,76 +2152,6 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/query:
|
||||
get:
|
||||
tags:
|
||||
- Query
|
||||
summary: query influx with specified return formatting. The spec and query fields are mutually exclusive.
|
||||
parameters:
|
||||
- in: query
|
||||
name: org
|
||||
description: specifies the organization of the resource
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: query
|
||||
description: query script to execute.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: header
|
||||
name: Authorization
|
||||
description: the authorization header should be in the format of `Token <key>`
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: query results
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
result,table,_start,_stop,_time,region,host,_value
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:00Z,east,A,15.43
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:20Z,east,B,59.25
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:40Z,east,C,52.62
|
||||
'400':
|
||||
description: error processing query
|
||||
headers:
|
||||
X-Influx-Error:
|
||||
description: error string describing the problem
|
||||
schema:
|
||||
type: string
|
||||
X-Influx-Reference:
|
||||
description: reference code unique to the error type
|
||||
schema:
|
||||
type: integer
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
error,reference
|
||||
Failed to parse query,897
|
||||
default:
|
||||
description: internal server error
|
||||
headers:
|
||||
X-Influx-Error:
|
||||
description: error string describing the problem
|
||||
schema:
|
||||
type: string
|
||||
X-Influx-Reference:
|
||||
description: reference code unique to the error type
|
||||
schema:
|
||||
type: integer
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
error,reference
|
||||
Failed to parse query,897
|
||||
post:
|
||||
tags:
|
||||
- Query
|
||||
|
@ -2243,6 +2173,7 @@ paths:
|
|||
type: string
|
||||
enum:
|
||||
- application/json
|
||||
- application/vnd.flux
|
||||
- in: header
|
||||
name: Authorization
|
||||
description: the authorization header should be in the format of `Token <key>`
|
||||
|
@ -2259,6 +2190,9 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Query"
|
||||
application/vnd.flux:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: query results
|
||||
|
@ -6188,4 +6122,4 @@ components:
|
|||
protos:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Proto"
|
||||
$ref: "#/components/schemas/Proto"
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -330,23 +332,32 @@ func QueryRequestFromProxyRequest(req *query.ProxyRequest) (*QueryRequest, error
|
|||
|
||||
func decodeQueryRequest(ctx context.Context, r *http.Request, svc platform.OrganizationService) (*QueryRequest, error) {
|
||||
var req QueryRequest
|
||||
// TODO(desa): I'm not sure I like this kind of conditional logic, but it feels better than
|
||||
// introducing another method that does this exact thing.
|
||||
if r.Method == http.MethodGet {
|
||||
qp := r.URL.Query()
|
||||
req.Query = qp.Get("query")
|
||||
if req.Query == "" {
|
||||
return nil, errors.New("query param \"query\" is required")
|
||||
|
||||
var contentType = "application/json"
|
||||
if ct := r.Header.Get("Content-Type"); ct != "" {
|
||||
contentType = ct
|
||||
}
|
||||
mt, _, err := mime.ParseMediaType(contentType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch mt {
|
||||
case "application/vnd.flux":
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
req.Query = string(body)
|
||||
case "application/json":
|
||||
fallthrough
|
||||
default:
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
req = req.WithDefaults()
|
||||
err := req.Validate()
|
||||
if err != nil {
|
||||
if err := req.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ func NewFluxHandler() *FluxHandler {
|
|||
}
|
||||
|
||||
h.HandlerFunc("POST", fluxPath, h.handleQuery)
|
||||
h.HandlerFunc("GET", fluxPath, h.handleQuery)
|
||||
h.HandlerFunc("POST", "/api/v2/query/ast", h.postFluxAST)
|
||||
h.HandlerFunc("POST", "/api/v2/query/analyze", h.postQueryAnalyze)
|
||||
h.HandlerFunc("POST", "/api/v2/query/spec", h.postFluxSpec)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -395,6 +396,35 @@ func Test_decodeQueryRequest(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid query request with explict content-type",
|
||||
args: args{
|
||||
r: func() *http.Request {
|
||||
r := httptest.NewRequest("POST", "/", bytes.NewBufferString(`{"query": "from()"}`))
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
return r
|
||||
}(),
|
||||
svc: &mock.OrganizationService{
|
||||
FindOrganizationF: func(ctx context.Context, filter platform.OrganizationFilter) (*platform.Organization, error) {
|
||||
return &platform.Organization{
|
||||
ID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &QueryRequest{
|
||||
Query: "from()",
|
||||
Type: "flux",
|
||||
Dialect: QueryDialect{
|
||||
Delimiter: ",",
|
||||
DateTimeFormat: "RFC3339",
|
||||
Header: func(x bool) *bool { return &x }(true),
|
||||
},
|
||||
Org: &platform.Organization{
|
||||
ID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error decoding json",
|
||||
args: args{
|
||||
|
@ -465,9 +495,13 @@ func Test_decodeProxyQueryRequest(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "valid get query request",
|
||||
name: "valid post vnd.flux query request",
|
||||
args: args{
|
||||
r: httptest.NewRequest("GET", "/api/v2/query?query=from(bucket%3A%20%22mybucket%22)&org=myorg", nil),
|
||||
r: func() *http.Request {
|
||||
r := httptest.NewRequest("POST", "/api/v2/query?org=myorg", strings.NewReader(`from(bucket: "mybucket")`))
|
||||
r.Header.Set("Content-Type", "application/vnd.flux")
|
||||
return r
|
||||
}(),
|
||||
svc: &mock.OrganizationService{
|
||||
FindOrganizationF: func(ctx context.Context, filter platform.OrganizationFilter) (*platform.Organization, error) {
|
||||
return &platform.Organization{
|
||||
|
|
|
@ -2638,72 +2638,6 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/query:
|
||||
get:
|
||||
tags:
|
||||
- Query
|
||||
summary: query influx with specified return formatting. The spec and query fields are mutually exclusive.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TraceSpan'
|
||||
- in: query
|
||||
name: org
|
||||
description: specifies the organization of the resource
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: query
|
||||
description: query script to execute.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: query results
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
result,table,_start,_stop,_time,region,host,_value
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:00Z,east,A,15.43
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:20Z,east,B,59.25
|
||||
mean,0,2018-05-08T20:50:00Z,2018-05-08T20:51:00Z,2018-05-08T20:50:40Z,east,C,52.62
|
||||
'400':
|
||||
description: error processing query
|
||||
headers:
|
||||
X-Influx-Error:
|
||||
description: error string describing the problem
|
||||
schema:
|
||||
type: string
|
||||
X-Influx-Reference:
|
||||
description: reference code unique to the error type
|
||||
schema:
|
||||
type: integer
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
error,reference
|
||||
Failed to parse query,897
|
||||
default:
|
||||
description: internal server error
|
||||
headers:
|
||||
X-Influx-Error:
|
||||
description: error string describing the problem
|
||||
schema:
|
||||
type: string
|
||||
X-Influx-Reference:
|
||||
description: reference code unique to the error type
|
||||
schema:
|
||||
type: integer
|
||||
content:
|
||||
text/csv:
|
||||
schema:
|
||||
type: string
|
||||
example: >
|
||||
error,reference
|
||||
Failed to parse query,897
|
||||
post:
|
||||
tags:
|
||||
- Query
|
||||
|
@ -2726,6 +2660,7 @@ paths:
|
|||
type: string
|
||||
enum:
|
||||
- application/json
|
||||
- application/vnd.flux
|
||||
- in: query
|
||||
name: org
|
||||
description: specifies the name of the organization executing the query.
|
||||
|
@ -2742,6 +2677,9 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Query"
|
||||
application/vnd.flux:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: query results
|
||||
|
|
Loading…
Reference in New Issue