Skip to content

Commit b8a0151

Browse files
committed
Skips content encoding of empty entities. Attempting to encode an empty entity with an encoder such as GZIP will result in a non-empty entity (a GZIP preamble) which is problematic --especially when a 204 is returned by a handler.
1 parent 793ffac commit b8a0151

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

webserver/tests/webserver/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,10 @@
6363
<artifactId>helidon-logging-jul</artifactId>
6464
<scope>test</scope>
6565
</dependency>
66+
<dependency>
67+
<groupId>io.helidon.http.encoding</groupId>
68+
<artifactId>helidon-http-encoding-gzip</artifactId>
69+
<scope>test</scope>
70+
</dependency>
6671
</dependencies>
6772
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.webserver.tests;
17+
18+
import io.helidon.http.HeaderNames;
19+
import io.helidon.http.Status;
20+
import io.helidon.logging.common.LogConfig;
21+
import io.helidon.webclient.http1.Http1Client;
22+
import io.helidon.webclient.http1.Http1ClientResponse;
23+
import io.helidon.webserver.http.HttpRules;
24+
import io.helidon.webserver.testing.junit5.ServerTest;
25+
import io.helidon.webserver.testing.junit5.SetUpRoute;
26+
27+
import org.junit.jupiter.api.Test;
28+
29+
import static org.hamcrest.CoreMatchers.is;
30+
import static org.hamcrest.MatcherAssert.assertThat;
31+
32+
@ServerTest
33+
class ContentEncodingEmptyTest {
34+
35+
private final Http1Client client;
36+
37+
ContentEncodingEmptyTest(Http1Client client) {
38+
this.client = client;
39+
}
40+
41+
@SetUpRoute
42+
static void routing(HttpRules rules) {
43+
LogConfig.configureRuntime();
44+
rules.post("/hello", (req, res) -> {
45+
res.status(Status.NO_CONTENT_204);
46+
res.send(); // empty entity
47+
});
48+
}
49+
50+
@Test
51+
void gzipEncodeEmptyEntity() {
52+
Http1ClientResponse res = client.post("hello")
53+
.header(HeaderNames.CONTENT_TYPE, "application/json")
54+
.header(HeaderNames.ACCEPT_ENCODING, "gzip")
55+
.request();
56+
assertThat(res.status().code(), is(204));
57+
}
58+
}

webserver/webserver/src/main/java/io/helidon/webserver/http/ServerResponseBase.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -203,6 +203,10 @@ protected MediaContext mediaContext() {
203203
* @return encoded bytes
204204
*/
205205
protected byte[] entityBytes(byte[] configuredEntity) {
206+
// do not try to content encode an empty entity
207+
if (configuredEntity.length == 0) {
208+
return configuredEntity;
209+
}
206210
byte[] entity = configuredEntity;
207211
if (contentEncodingContext.contentEncodingEnabled()) {
208212
ContentEncoder encoder = contentEncodingContext.encoder(requestHeaders);

0 commit comments

Comments
 (0)