diff --git a/cmd/query/app/apiv3/http_gateway.go b/cmd/query/app/apiv3/http_gateway.go index 6672de22917..0470cf8b60b 100644 --- a/cmd/query/app/apiv3/http_gateway.go +++ b/cmd/query/app/apiv3/http_gateway.go @@ -123,6 +123,17 @@ func (h *HTTPGateway) returnTraces(traces []ptrace.Traces, err error, w http.Res if h.tryHandleError(w, err, http.StatusInternalServerError) { return } + if len(traces) == 0 { + errorResponse := api_v3.GRPCGatewayError{ + Error: &api_v3.GRPCGatewayError_GRPCGatewayErrorDetails{ + HttpCode: http.StatusNotFound, + Message: "No traces found", + }, + } + resp, _ := json.Marshal(&errorResponse) + http.Error(w, string(resp), http.StatusNotFound) + return + } // TODO: the response should be streamed back to the client // https://github.com/jaegertracing/jaeger/issues/6467 combinedTrace := ptrace.NewTraces() diff --git a/cmd/query/app/apiv3/http_gateway_test.go b/cmd/query/app/apiv3/http_gateway_test.go index 59707b73b2d..c42e8118d20 100644 --- a/cmd/query/app/apiv3/http_gateway_test.go +++ b/cmd/query/app/apiv3/http_gateway_test.go @@ -150,6 +150,39 @@ func TestHTTPGatewayGetTrace(t *testing.T) { } } +func TestHTTPGatewayGetTraceEmptyResponse(t *testing.T) { + gw := setupHTTPGatewayNoServer(t, "") + gw.reader.On("GetTraces", matchContext, mock.AnythingOfType("tracestore.GetTraceParams")). + Return(iter.Seq2[[]ptrace.Traces, error](func(yield func([]ptrace.Traces, error) bool) { + yield([]ptrace.Traces{}, nil) + })).Once() + + r, err := http.NewRequest(http.MethodGet, "/api/v3/traces/1", nil) + require.NoError(t, err) + w := httptest.NewRecorder() + gw.router.ServeHTTP(w, r) + assert.Equal(t, http.StatusNotFound, w.Code) + assert.Contains(t, w.Body.String(), "No traces found") +} + +func TestHTTPGatewayFindTracesEmptyResponse(t *testing.T) { + q, qp := mockFindQueries() + r, err := http.NewRequest(http.MethodGet, "/api/v3/traces?"+q.Encode(), nil) + require.NoError(t, err) + w := httptest.NewRecorder() + + gw := setupHTTPGatewayNoServer(t, "") + gw.reader. + On("FindTraces", matchContext, qp). + Return(iter.Seq2[[]ptrace.Traces, error](func(yield func([]ptrace.Traces, error) bool) { + yield([]ptrace.Traces{}, nil) + })).Once() + + gw.router.ServeHTTP(w, r) + assert.Equal(t, http.StatusNotFound, w.Code) + assert.Contains(t, w.Body.String(), "No traces found") +} + func TestHTTPGatewayGetTraceMalformedInputErrors(t *testing.T) { testCases := []struct { name string @@ -163,17 +196,17 @@ func TestHTTPGatewayGetTraceMalformedInputErrors(t *testing.T) { }, { name: "TestGetTraceWithInvalidStartTime", - requestUrl: "/api/v3/traces/123?start_time=abc", + requestUrl: "/api/v3/traces/1?start_time=abc", expectedError: "malformed parameter start_time", }, { name: "TestGetTraceWithInvalidEndTime", - requestUrl: "/api/v3/traces/123?end_time=xyz", + requestUrl: "/api/v3/traces/1?end_time=xyz", expectedError: "malformed parameter end_time", }, { name: "TestGetTraceWithInvalidRawTraces", - requestUrl: "/api/v3/traces/123?raw_traces=foobar", + requestUrl: "/api/v3/traces/1?raw_traces=foobar", expectedError: "malformed parameter raw_traces", }, } @@ -202,7 +235,7 @@ func TestHTTPGatewayGetTraceInternalErrors(t *testing.T) { yield([]ptrace.Traces{}, assert.AnError) })).Once() - r, err := http.NewRequest(http.MethodGet, "/api/v3/traces/123", nil) + r, err := http.NewRequest(http.MethodGet, "/api/v3/traces/1", nil) require.NoError(t, err) w := httptest.NewRecorder() gw.router.ServeHTTP(w, r)