diff options
13 files changed, 62 insertions, 30 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/ExtendedResponse.java b/container-core/src/main/java/com/yahoo/container/jdisc/ExtendedResponse.java index adfb461c122..1aa69ba865f 100644 --- a/container-core/src/main/java/com/yahoo/container/jdisc/ExtendedResponse.java +++ b/container-core/src/main/java/com/yahoo/container/jdisc/ExtendedResponse.java @@ -23,9 +23,8 @@ public abstract class ExtendedResponse extends AsyncHttpResponse { } @Override - public abstract void render(OutputStream output, - ContentChannel networkChannel, CompletionHandler handler) - throws IOException; + public abstract void render(OutputStream output, ContentChannel networkChannel, CompletionHandler handler) + throws IOException; /** * @return user name performing the request diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java index 205dbcd9ce8..6600a36f9db 100644 --- a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java +++ b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java @@ -34,12 +34,9 @@ public abstract class ThreadedHttpRequestHandler extends ThreadedRequestHandler public static final String DATE = "Date"; private static final String RENDERING_ERRORS = "rendering_errors"; - /** - * Logger for subclasses. - */ + /** Logger for subclasses */ protected final Logger log; - public ThreadedHttpRequestHandler(Executor executor) { this(executor, null); } diff --git a/container-core/src/main/resources/configdefinitions/container-http.def b/container-core/src/main/resources/configdefinitions/container-http.def index b3a1a8d7d41..ae0fecae549 100644 --- a/container-core/src/main/resources/configdefinitions/container-http.def +++ b/container-core/src/main/resources/configdefinitions/container-http.def @@ -8,6 +8,9 @@ enabled bool default=false ## Buffer size for incoming requests requestbuffersize int default=65536 +## If non-empty, handlers should emit a header containing this string as key and the local host name as value +hostResponseHeaderKey string default="" + ## Which port to listen on for search queries port.search int default=8081 @@ -16,3 +19,4 @@ port.host string default="" ## Whether to serve files on the same port as search queries. fileserver.throughsearch bool default=true + diff --git a/container-core/src/main/resources/configdefinitions/qr-templates.def b/container-core/src/main/resources/configdefinitions/qr-templates.def index a1d5a4f36e0..5ba2a387b3b 100644 --- a/container-core/src/main/resources/configdefinitions/qr-templates.def +++ b/container-core/src/main/resources/configdefinitions/qr-templates.def @@ -1,4 +1,6 @@ # Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +# Not used +# TODO: Remove on Vespa 7 version=8 namespace=container.core 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 56bd3fc57b3..01e56e73cae 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 @@ -13,6 +13,7 @@ import com.yahoo.component.provider.ComponentRegistry; import com.yahoo.container.Container; import com.yahoo.container.QrSearchersConfig; import com.yahoo.container.core.ChainsConfig; +import com.yahoo.container.core.ContainerHttpConfig; import com.yahoo.container.core.QrTemplatesConfig; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; @@ -23,6 +24,7 @@ import com.yahoo.container.protect.FreezeDetector; import com.yahoo.jdisc.Metric; import com.yahoo.language.Linguistics; import com.yahoo.log.LogLevel; +import com.yahoo.net.HostName; import com.yahoo.net.UriTools; import com.yahoo.prelude.IndexFacts; import com.yahoo.prelude.IndexModel; @@ -55,6 +57,8 @@ import com.yahoo.statistics.Value; import com.yahoo.vespa.configdefinition.SpecialtokensConfig; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; @@ -104,6 +108,11 @@ public class SearchHandler extends LoggingRequestHandler { private final Linguistics linguistics; private final CompiledQueryProfileRegistry queryProfileRegistry; + + /** If present, responses from this will set the HTTP response header with this key to the host name of this */ + private final Optional<String> hostResponseHeaderKey; + + private final String selfHostname = HostName.getLocalhost(); private final class MeanConnections implements Callback { @@ -131,7 +140,8 @@ public class SearchHandler extends LoggingRequestHandler { final Executor executor, final AccessLog accessLog, final QueryProfilesConfig queryProfileConfig, - final ComponentRegistry<Searcher> searchers) { + final ComponentRegistry<Searcher> searchers, + final ContainerHttpConfig containerHttpConfig) { super(executor, accessLog, metric, true); log.log(LogLevel.DEBUG, "SearchHandler.init " + System.identityHashCode(this)); searchChainRegistry = new SearchChainRegistry(searchers); @@ -151,9 +161,33 @@ public class SearchHandler extends LoggingRequestHandler { .setLogMean(true).setLogMin(true) .setNameExtension(true) .setCallback(new MeanConnections())); + + this.hostResponseHeaderKey = containerHttpConfig.hostResponseHeaderKey().equals("") ? + Optional.empty() : Optional.of( containerHttpConfig.hostResponseHeaderKey()); + } + + /** @deprecated use the constructor with ContainerHttpConfig */ + // TODO: Remove on Vespa 7 + @Deprecated + public SearchHandler( + final ChainsConfig chainsConfig, + final IndexInfoConfig indexInfo, + final QrSearchersConfig clusters, + final SpecialtokensConfig specialtokens, + final Statistics statistics, + final Linguistics linguistics, + final Metric metric, + final ComponentRegistry<Renderer> renderers, + final Executor executor, + final AccessLog accessLog, + final QueryProfilesConfig queryProfileConfig, + final ComponentRegistry<Searcher> searchers) { + this (chainsConfig, indexInfo, clusters, specialtokens, statistics, linguistics, metric, renderers, executor, + accessLog, queryProfileConfig, searchers, new ContainerHttpConfig(new ContainerHttpConfig.Builder())); } /** @deprecated use the constructor without deprecated parameters */ + // TODO: Remove on Vespa 7 @Deprecated public SearchHandler( final ChainsConfig chainsConfig, @@ -176,7 +210,7 @@ public class SearchHandler extends LoggingRequestHandler { private void setupSearchChainRegistry(final ComponentRegistry<Searcher> searchers, final ChainsConfig chainsConfig) { - final ChainsModel chainsModel = ChainsModelBuilder.buildFromConfig(chainsConfig); + ChainsModel chainsModel = ChainsModelBuilder.buildFromConfig(chainsConfig); ChainsConfigurer.prepareChainRegistry(searchChainRegistry, chainsModel, searchers); searchChainRegistry.freeze(); } @@ -253,9 +287,8 @@ public class SearchHandler extends LoggingRequestHandler { Query query = new Query(request, queryProfile); boolean benchmarkCoverage = VespaHeaders.benchmarkCoverage(benchmarkOutput, request.getJDiscRequest().headers()); - if (benchmarkCoverage) { + if (benchmarkCoverage) query.getPresentation().setReportCoverage(true); - } // Find and execute search chain if we have a valid query String invalidReason = query.validate(); @@ -294,12 +327,14 @@ public class SearchHandler extends LoggingRequestHandler { } // Transform result to response - HttpSearchResponse response = new HttpSearchResponse(getHttpResponseStatus(request, result), + HttpSearchResponse response = new HttpSearchResponse(getHttpResponseStatus(request, result), result, query, renderer); - if (benchmarkOutput) { + if (hostResponseHeaderKey.isPresent()) + response.headers().add(hostResponseHeaderKey.get(), selfHostname); + + if (benchmarkOutput) VespaHeaders.benchmarkOutput(response.headers(), benchmarkCoverage, response.getTiming(), response.getHitCounts(), getErrors(result), response.getCoverage()); - } return response; } @@ -322,11 +357,7 @@ public class SearchHandler extends LoggingRequestHandler { } Chain<Searcher> searchChain = searchChainRegistry.getChain(chainName); - if (searchChain == null && explicitChainName == null) { // explicit - // search chain - // not found - // should cause - // error + if (searchChain == null && explicitChainName == null) { // explicit chain not found should cause error chainName = fallbackSearchChain; searchChain = searchChainRegistry.getChain(chainName); } 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 d1cbf403c1a..f7fbf6813bc 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 @@ -11,6 +11,7 @@ import com.yahoo.container.jdisc.RequestHandlerTestDriver; import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.handler.RequestHandler; +import com.yahoo.net.HostName; import com.yahoo.processing.handler.ResponseStatus; import com.yahoo.search.Query; import com.yahoo.search.Result; @@ -33,6 +34,8 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.List; +import java.util.Map; import java.util.concurrent.Executors; import static org.hamcrest.CoreMatchers.containsString; @@ -49,6 +52,9 @@ import static org.junit.Assert.assertTrue; public class SearchHandlerTestCase { private static final String testDir = "src/test/java/com/yahoo/search/handler/test/config"; + private static final String myHostnameHeader = "my-hostname-header"; + private static final String selfHostname = HostName.getLocalhost(); + private static String tempDir = ""; private static String configId = null; @@ -104,13 +110,6 @@ public class SearchHandlerTestCase { ); } - private String render(AsyncHttpResponse response) throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - response.render(stream, null, null); - response.complete(); - return stream.toString(); - } - @Test public void testFailing() throws Exception { assertTrue(driver.sendRequest("http://localhost?query=test&searchChain=classLoadingError").readAll().contains("NoClassDefFoundError")); @@ -314,6 +313,7 @@ public class SearchHandlerTestCase { private void assertOkResult(RequestHandlerTestDriver.MockResponseHandler response, String expected) { assertEquals(expected, response.readAll()); assertEquals(200, response.getStatus()); + assertEquals(selfHostname, response.getResponse().headers().get(myHostnameHeader).get(0)); } @Test diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/container-http.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/container-http.cfg new file mode 100644 index 00000000000..2bea347c5f4 --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/container-http.cfg @@ -0,0 +1 @@ +hostResponseHeaderKey my-hostname-header diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/container-http.cfg b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/container-http.cfg new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/container-http.cfg diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/container-http.cfg b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/container-http.cfg new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/container-http.cfg diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java index 18073a1cedd..4d611e3e842 100644 --- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java @@ -35,7 +35,6 @@ public class SearchChainConfigurerTestCase { private static final String testDir = "src/test/java/com/yahoo/search/searchchain/config/test/"; - public void cleanup(File cfgDir) { if (cfgDir.exists()) { for (File f : cfgDir.listFiles()) { @@ -137,6 +136,7 @@ public class SearchChainConfigurerTestCase { copyFile(testDir + "index-info.cfg", cfgDir + "/index-info.cfg"); copyFile(testDir + "specialtokens.cfg", cfgDir + "/specialtokens.cfg"); copyFile(testDir + "three-searchers.cfg", cfgDir + "/chains.cfg"); + copyFile(testDir + "container-http.cfg", cfgDir + "/container-http.cfg"); createComponentsConfig(testDir + "three-searchers.cfg", testDir + "handlers.cfg", cfgDir + "/components.cfg"); printFile(new File(cfgDir + "/int.cfg"), "intVal 16\n"); printFile(new File(cfgDir + "/string.cfg"), "stringVal \"testSearcherConfigUpdate\"\n"); @@ -189,6 +189,7 @@ public class SearchChainConfigurerTestCase { copyFile(testDir + "index-info.cfg", cfgDir + "/index-info.cfg"); copyFile(testDir + "specialtokens.cfg", cfgDir + "/specialtokens.cfg"); copyFile(testDir + "chainsConfigUpdate_1.cfg", cfgDir + "/chains.cfg"); + copyFile(testDir + "container-http.cfg", cfgDir + "/container-http.cfg"); createComponentsConfig(testDir + "chainsConfigUpdate_1.cfg", testDir + "handlers.cfg", cfgDir + "/components.cfg"); HandlersConfigurerTestWrapper configurer = new HandlersConfigurerTestWrapper("dir:" + cfgDir); diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/container-http.cfg b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/container-http.cfg new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/container-http.cfg diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/container-http.cfg b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/container-http.cfg new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/container-http.cfg diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java index 5cd8dec0af9..cf54c546eb7 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java @@ -23,10 +23,8 @@ import java.util.List; public class HttpResponse extends Response implements ServletOrJdiscHttpResponse { private final HeaderFields trailers = new HeaderFields(); - private final StringBuffer accessLogExtra = new StringBuffer(); private boolean chunkedEncodingEnabled = true; private String message; - private final Request request; public interface Status extends Response.Status { @@ -37,7 +35,6 @@ public class HttpResponse extends Response implements ServletOrJdiscHttpResponse protected HttpResponse(Request request, int status, String message, Throwable error) { super(status, error); this.message = message; - this.request = request; } public boolean isChunkedEncodingEnabled() { |