diff options
author | Henrik <henrik.hoiness@online.no> | 2018-06-21 09:57:38 +0200 |
---|---|---|
committer | Henrik <henrik.hoiness@online.no> | 2018-06-22 09:21:06 +0200 |
commit | d42507a3cffe99007b61f72d4c53bd43f9298c6e (patch) | |
tree | 11b9e178a3fe9dae007d10c35ec5c2a75c4a4c58 /container-search | |
parent | 0041440b22ea63f22d4848f62fa690babc2b872e (diff) |
Added simple handling of JSON-queries.
Diffstat (limited to 'container-search')
4 files changed, 123 insertions, 14 deletions
diff --git a/container-search/pom.xml b/container-search/pom.xml index cdfcdb2434a..f04520398af 100644 --- a/container-search/pom.xml +++ b/container-search/pom.xml @@ -61,6 +61,11 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>com.yahoo.vespa</groupId> <artifactId>container-accesslogging</artifactId> <version>${project.version}</version> diff --git a/container-search/src/main/java/com/yahoo/search/Query.java b/container-search/src/main/java/com/yahoo/search/Query.java index ab6976e29d9..2f6b2df1407 100644 --- a/container-search/src/main/java/com/yahoo/search/Query.java +++ b/container-search/src/main/java/com/yahoo/search/Query.java @@ -56,6 +56,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * A search query containing all the information required to produce a Result. @@ -270,6 +271,7 @@ public class Query extends com.yahoo.processing.Request implements Cloneable { this(""); } + /** * Construct a query from a string formatted in the http style, e.g <code>?query=test&offset=10&hits=13</code> * The query must be uri encoded. @@ -278,6 +280,16 @@ public class Query extends com.yahoo.processing.Request implements Cloneable { this(query, null); } + + /** + * Creates a query from a request + * + * @param request the HTTP request from which this is created + */ + public Query(HttpRequest request) { + this(request, null); + } + /** * Construct a query from a string formatted in the http style, e.g <code>?query=test&offset=10&hits=13</code> * The query must be uri encoded. @@ -299,15 +311,27 @@ public class Query extends com.yahoo.processing.Request implements Cloneable { } /** - * Creates a query from a request + * Creates a query from a request containing a JSON-query. * - * @param request the HTTP request from which this is created + * @param request the HTTP request from which this is created. + * @param requestMap the property map of the query. + * @param queryProfile the query profile to use for this query, or null if none. */ - public Query(HttpRequest request) { - this(request, null); + public Query(HttpRequest request, Map<String, String> requestMap, CompiledQueryProfile queryProfile) { + + super(new QueryPropertyAliases(propertyAliases)); + this.httpRequest = request; + init(requestMap, queryProfile); } + + private void init(Map<String, String> requestMap, CompiledQueryProfile queryProfile) { + String content = requestMap.entrySet() + .stream() + .map(e -> e.getKey() + "=\"" + e.getValue() + "\"") + .collect(Collectors.joining(", ")); + System.out.println(content); startTime = System.currentTimeMillis(); if (queryProfile != null) { // Move all request parameters to the query profile just to validate that the parameter settings are legal diff --git a/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java b/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java index e9e4e34727c..3b2ee2fd197 100644 --- a/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java +++ b/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java @@ -55,15 +55,19 @@ import com.yahoo.statistics.Statistics; import com.yahoo.statistics.Value; import com.yahoo.vespa.configdefinition.SpecialtokensConfig; import edu.umd.cs.findbugs.annotations.NonNull; +import org.apache.commons.io.IOUtils; +import org.json.*; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Optional; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * Handles search request. @@ -233,6 +237,9 @@ public class SearchHandler extends LoggingRequestHandler { } catch (RuntimeException e) { // Make sure we generate a valid response even on unexpected errors log.log(Level.WARNING, "Failed handling " + request, e); return internalServerErrorResponse(request, e); + } catch (JSONException e) { + e.printStackTrace(); + return invalidJsonResponse(request, e); } } finally { requestsInFlight.decrementAndGet(); @@ -275,14 +282,44 @@ public class SearchHandler extends LoggingRequestHandler { return errorResponse(request, ErrorMessage.createInternalServerError(Exceptions.toMessageString(e))); } - private HttpSearchResponse handleBody(HttpRequest request) { + private HttpResponse invalidJsonResponse(HttpRequest request, JSONException e) { + return errorResponse(request, ErrorMessage.createBadRequest(Exceptions.toMessageString(e))); + } + + private HttpSearchResponse handleBody(HttpRequest request) throws JSONException { // Find query profile String queryProfileName = request.getProperty("queryProfile"); CompiledQueryProfile queryProfile = queryProfileRegistry.findQueryProfile(queryProfileName); boolean benchmarkOutput = VespaHeaders.benchmarkOutput(request); + // Create query - Query query = new Query(request, queryProfile); + Query query; + + //SLETT LINJE UNDER + Map<String, String> a = null; + + if (checkJSON(request.getData()) && request.getMethod() == com.yahoo.jdisc.http.HttpRequest.Method.POST) { + JSONObject json = null; + + try { + + String jsonString = "{" + IOUtils.toString(request.getData(), StandardCharsets.UTF_8); + System.out.println("Received JSON: " + jsonString); + json = new JSONObject(jsonString); + } catch (IOException e) { e.printStackTrace(); + } + + + Map<String, String> requestMap = createRequestMapping(json); + query = new Query(request, requestMap, queryProfile); + + + } else { + query = new Query(request, queryProfile); + + } + boolean benchmarkCoverage = VespaHeaders.benchmarkCoverage(benchmarkOutput, request.getJDiscRequest().headers()); @@ -552,4 +589,47 @@ public class SearchHandler extends LoggingRequestHandler { return searchChainRegistry; } + private boolean checkJSON(InputStream inputStream) { + try { + byte[] bytes = new byte[1]; + + inputStream.read(bytes); + if (bytes[0] == 0x7B) { + // InputStream is believed to be JSON + return true; + } + } catch (IOException e) { + // Something went wrong + } + + return false; + + } + + private Map<String, String> createRequestMapping(JSONObject json) { + // Create mapping + Map<String, String> requestMap = new HashMap<String, String>(); + Iterator<?> keys = json.keys(); + + while( keys.hasNext() ){ + String key = (String)keys.next(); + String value = null; + try { + value = json.getString(key); + requestMap.put(key, value); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + return requestMap; + + + + } + + + } + + diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java b/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java index ce40bd1f06b..30a5d637767 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java @@ -23,6 +23,7 @@ import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; import com.yahoo.search.searchchain.Execution; import com.yahoo.search.searchchain.config.test.SearchChainConfigurerTestCase; +import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -30,12 +31,9 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.net.URI; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.Executors; import static org.hamcrest.CoreMatchers.containsString; @@ -187,6 +185,8 @@ public class SearchHandlerTestCase { } } + + // Query handling takes a different code path when a query profile is active, so we test both paths. @Test public void testInvalidQueryParamWithQueryProfile() throws Exception { |