/// <summary> /// Internal implementation of the pass through API. /// </summary> /// <returns>Http response from the metadata client.</returns> internal async Task <IActionResult> PassthroughInternal() { HttpContext.Request.Path = ControllerExtractMethods.ReplaceBackTemplateString(HttpContext.Request.Path.Value); var remoteResponse = await ForwardMessageToMetadataClient( clientFactory, new HttpRequestMessageFeature(HttpContext).HttpRequestMessage); HttpContext.Response.RegisterForDispose(remoteResponse); return(new HttpResponseMessageResult(remoteResponse)); }
public async Task <IActionResult> MultiSearchAsync( [FromServices] RequestContext requestContext) { try { var rawQueryData = await ExtractBodyAsync(); Ensure.IsNotNull(rawQueryData, nameof(rawQueryData), "Invalid request body. rawQueryData is null.", logger); // Extract Query var(header, query) = ControllerExtractMethods.SplitQueryBody(rawQueryData); return(await SearchInternalAsync(header, query, requestContext)); } catch (Exception exception) { logger.LogError(exception, "Failed to execute search query, returning 500."); return(BadRequest(exception)); } }
/// <summary> /// Internal implementation of the search API logic. /// Mainly used to improve testability (as certain parameters needs to be extracted from the body). /// </summary> /// <param name="totalHits">totalHits parameter coming from Kibana (currently not used).</param> /// <param name="ignoreThrottled">ignoreThrottled parameter coming from Kibana (currently not used).</param> /// <param name="rawQueryData">Body Payload.</param> /// <param name="requestContext">An object that represents properties of the entire request process.</param> /// <returns>An ElasticResponse object.</returns> internal async Task <IActionResult> SearchInternalAsync( bool totalHits, bool ignoreThrottled, string rawQueryData, RequestContext requestContext) { var sw = new Stopwatch(); sw.Start(); Ensure.IsNotNull(rawQueryData, nameof(rawQueryData), "Invalid request body. rawQueryData is null.", logger); // Extract Query (string header, string query) = ControllerExtractMethods.SplitQueryBody(rawQueryData); Ensure.IsNotNullOrEmpty(header, nameof(header), "Invalid request body. header is null or empty.", logger); Ensure.IsNotNullOrEmpty(query, nameof(query), "Invalid request body. query is null or empty.", logger); // Translate Query (QueryData translatedQuery, bool error, ElasticErrorResponse errorResponse)translateResponse = TryFuncReturnsElasticError( () => { return(translator.Translate(header, query)); }, UnknownIndexName); // At this point we don't know the index name. if (translateResponse.error) { return(Ok(translateResponse.errorResponse)); } logger.LogDebug("Translated query:\n{@QueryCommandText}", translateResponse.translatedQuery.QueryCommandText.ToSensitiveData()); // Execute Query ((TimeSpan timeTaken, IDataReader dataReader)response, bool error, ElasticErrorResponse errorResponse)queryResponse = await TryAsyncFuncReturnsElasticError( async() => { return(await queryExecutor.ExecuteQueryAsync(translateResponse.translatedQuery, requestContext)); }, translateResponse.translatedQuery.IndexName); if (queryResponse.error) { return(Ok(queryResponse.errorResponse)); } // Parse Response (ElasticResponse elasticResponse, bool error, ElasticErrorResponse errorResponse)parseResponse = TryFuncReturnsElasticError( () => { return(responseParser.Parse(queryResponse.response.dataReader, translateResponse.translatedQuery, queryResponse.response.timeTaken)); }, translateResponse.translatedQuery.IndexName); if (parseResponse.error) { return(Ok(parseResponse.errorResponse)); } sw.Stop(); logger.LogDebug($"[metric] search request duration: {sw.Elapsed}"); return(Ok(parseResponse.elasticResponse)); }