Skip to content

Commit d68a094

Browse files
authored
[8.15] RestRequest parameter parsing should not cause 500 error (elastic#112605) (elastic#112656)
Currently, RestRequest throws IllegalStateExceptions in a few places which leads to 500 errors on the client side and e.g. turn up as warnings in the "rest.suppressed" error log. By changing them to IllegalArgumentExceptions we can change these to 400 (Bad Request) error codes. Closes elastic#112604
1 parent d33cf61 commit d68a094

File tree

3 files changed

+17
-8
lines changed

3 files changed

+17
-8
lines changed

server/src/main/java/org/elasticsearch/rest/RestRequest.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.ElasticsearchParseException;
1313
import org.elasticsearch.ElasticsearchStatusException;
1414
import org.elasticsearch.common.Strings;
15+
import org.elasticsearch.common.ValidationException;
1516
import org.elasticsearch.common.bytes.BytesArray;
1617
import org.elasticsearch.common.bytes.BytesReference;
1718
import org.elasticsearch.common.unit.ByteSizeValue;
@@ -297,11 +298,17 @@ public final BytesReference requiredContent() {
297298
if (hasContent() == false) {
298299
throw new ElasticsearchParseException("request body is required");
299300
} else if (xContentType.get() == null) {
300-
throw new IllegalStateException("unknown content type");
301+
throwValidationException("unknown content type");
301302
}
302303
return content();
303304
}
304305

306+
private static void throwValidationException(String msg) {
307+
ValidationException unknownContentType = new ValidationException();
308+
unknownContentType.addValidationError(msg);
309+
throw unknownContentType;
310+
}
311+
305312
/**
306313
* Get the value of the header or {@code null} if not found. This method only retrieves the first header value if multiple values are
307314
* sent. Use of {@link #getAllHeaderValues(String)} should be preferred
@@ -561,12 +568,12 @@ public final Tuple<XContentType, BytesReference> contentOrSourceParam() {
561568
String source = param("source");
562569
String typeParam = param("source_content_type");
563570
if (source == null || typeParam == null) {
564-
throw new IllegalStateException("source and source_content_type parameters are required");
571+
throwValidationException("source and source_content_type parameters are required");
565572
}
566573
BytesArray bytes = new BytesArray(source);
567574
final XContentType xContentType = parseContentType(Collections.singletonList(typeParam));
568575
if (xContentType == null) {
569-
throw new IllegalStateException("Unknown value for source_content_type [" + typeParam + "]");
576+
throwValidationException("Unknown value for source_content_type [" + typeParam + "]");
570577
}
571578
return new Tuple<>(xContentType, bytes);
572579
}

server/src/test/java/org/elasticsearch/rest/RestRequestTests.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.elasticsearch.rest;
1010

1111
import org.elasticsearch.ElasticsearchParseException;
12+
import org.elasticsearch.common.ValidationException;
1213
import org.elasticsearch.common.bytes.BytesArray;
1314
import org.elasticsearch.common.bytes.BytesReference;
1415
import org.elasticsearch.core.CheckedConsumer;
@@ -32,6 +33,7 @@
3233
import static java.util.Collections.emptyMap;
3334
import static java.util.Collections.singletonMap;
3435
import static org.elasticsearch.rest.RestRequest.PATH_RESTRICTED;
36+
import static org.hamcrest.Matchers.containsString;
3537
import static org.hamcrest.Matchers.equalTo;
3638
import static org.hamcrest.Matchers.instanceOf;
3739
import static org.hamcrest.Matchers.is;
@@ -129,8 +131,8 @@ public void testContentOrSourceParam() throws IOException {
129131
.contentOrSourceParam()
130132
.v2()
131133
);
132-
e = expectThrows(IllegalStateException.class, () -> contentRestRequest("", Map.of("source", "stuff2")).contentOrSourceParam());
133-
assertEquals("source and source_content_type parameters are required", e.getMessage());
134+
e = expectThrows(ValidationException.class, () -> contentRestRequest("", Map.of("source", "stuff2")).contentOrSourceParam());
135+
assertThat(e.getMessage(), containsString("source and source_content_type parameters are required"));
134136
}
135137

136138
public void testHasContentOrSourceParam() throws IOException {
@@ -245,8 +247,8 @@ public void testRequiredContent() {
245247
.requiredContent()
246248
);
247249
assertEquals("request body is required", e.getMessage());
248-
e = expectThrows(IllegalStateException.class, () -> contentRestRequest("test", null, Collections.emptyMap()).requiredContent());
249-
assertEquals("unknown content type", e.getMessage());
250+
e = expectThrows(ValidationException.class, () -> contentRestRequest("test", null, Collections.emptyMap()).requiredContent());
251+
assertThat(e.getMessage(), containsString("unknown content type"));
250252
}
251253

252254
public void testMarkPathRestricted() {

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/RestRequestFilterTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public void testFilterUnknownContentTypeThrows() throws IOException {
115115
}
116116
RestRequestFilter filter = () -> Collections.singleton("root.second.third");
117117
RestRequest filtered = filter.getFilteredRequest(restRequest);
118-
IllegalStateException e = expectThrows(IllegalStateException.class, () -> filtered.content());
118+
Exception e = expectThrows(IllegalArgumentException.class, () -> filtered.content());
119119
assertThat(e.getMessage(), containsString("unknown content type"));
120120
}
121121

0 commit comments

Comments
 (0)