From 8cc22eb960d53905cab3697f4de88c8cd8278601 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Fri, 21 Oct 2016 16:44:50 -0400 Subject: [PATCH] Make sure HEAD / has 0 Content-Length (#21077) Before this commit `curl -XHEAD localhost:9200?pretty` would return `Content-Length: 1` and a body which is fairly upsetting to standards compliant tools. Now it'll return `Content-Length: 0` with an empty body like every other `HEAD` request. Relates to #21075 --- .../rest/action/RestMainAction.java | 3 +- .../test/rest/HeadBodyIsEmptyIT.java | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/HeadBodyIsEmptyIT.java diff --git a/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java b/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java index dca1c2c86d9..c1c1e220b28 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java @@ -23,6 +23,7 @@ import org.elasticsearch.action.main.MainAction; import org.elasticsearch.action.main.MainRequest; import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -60,7 +61,7 @@ public class RestMainAction extends BaseRestHandler { static BytesRestResponse convertMainResponse(MainResponse response, RestRequest request, XContentBuilder builder) throws IOException { RestStatus status = response.isAvailable() ? RestStatus.OK : RestStatus.SERVICE_UNAVAILABLE; if (request.method() == RestRequest.Method.HEAD) { - return new BytesRestResponse(status, builder); + return new BytesRestResponse(status, BytesRestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY); } // Default to pretty printing, but allow ?pretty=false to disable diff --git a/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/HeadBodyIsEmptyIT.java b/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/HeadBodyIsEmptyIT.java new file mode 100644 index 00000000000..c3a19e5ab34 --- /dev/null +++ b/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/HeadBodyIsEmptyIT.java @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.test.rest; + +import org.apache.http.entity.StringEntity; +import org.elasticsearch.client.Response; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Map; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; + +/** + * Tests that HTTP HEAD requests don't respond with a body. + */ +public class HeadBodyIsEmptyIT extends ESRestTestCase { + public void testHeadRoot() throws IOException { + headTestCase("/", emptyMap()); + headTestCase("/", singletonMap("pretty", "")); + headTestCase("/", singletonMap("pretty", "true")); + } + + private void createTestDoc() throws UnsupportedEncodingException, IOException { + client().performRequest("PUT", "test/test/1", emptyMap(), new StringEntity("{\"test\": \"test\"}")); + } + + public void testDocumentExists() throws IOException { + createTestDoc(); + headTestCase("test/test/1", emptyMap()); + headTestCase("test/test/1", singletonMap("pretty", "true")); + } + + public void testIndexExists() throws IOException { + createTestDoc(); + headTestCase("test", emptyMap()); + headTestCase("test", singletonMap("pretty", "true")); + } + + public void testTypeExists() throws IOException { + createTestDoc(); + headTestCase("test/test", emptyMap()); + headTestCase("test/test", singletonMap("pretty", "true")); + } + + private void headTestCase(String url, Map params) throws IOException { + Response response = client().performRequest("HEAD", url, params); + assertEquals(200, response.getStatusLine().getStatusCode()); + /* Check that the content-length header is always 0. This isn't what we should be doing in the long run but it is what we expect + * that we are *actually* doing. */ + assertEquals("We expect HEAD requests to have 0 Content-Length but " + url + " didn't", "0", response.getHeader("Content-Length")); + assertNull("HEAD requests shouldn't have a response body but " + url + " did", response.getEntity()); + } +}