Skip to content

Commit 1ea9f11

Browse files
author
Christoph Büscher
authored
Change ScriptException status to 400 (bad request) (#30861)
Currently failures to compile a script usually lead to a ScriptException, which inherits the 500 INTERNAL_SERVER_ERROR from ElasticsearchException if it does not contain another root cause. Instead, this should be a 400 Bad Request error. This PR changes this more generally for script compilation errors by changing ScriptException to return 400 (bad request) as status code. Closes #12315
1 parent 7c5abc0 commit 1ea9f11

File tree

15 files changed

+71
-39
lines changed

15 files changed

+71
-39
lines changed

docs/painless/painless-debugging.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Which shows that the class of `doc.first` is
4848
"java_class": "org.elasticsearch.index.fielddata.ScriptDocValues$Longs",
4949
...
5050
},
51-
"status": 500
51+
"status": 400
5252
}
5353
---------------------------------------------------------
5454
// TESTRESPONSE[s/\.\.\./"script_stack": $body.error.script_stack, "script": $body.error.script, "lang": $body.error.lang, "caused_by": $body.error.caused_by, "root_cause": $body.error.root_cause, "reason": $body.error.reason/]

docs/reference/migration/migrate_7_0/scripting.asciidoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ the getter methods for date objects were deprecated. These methods have
1111
now been removed. Instead, use `.value` on `date` fields, or explicitly
1212
parse `long` fields into a date object using
1313
`Instance.ofEpochMillis(doc["myfield"].value)`.
14+
15+
==== Script errors will return as `400` error codes
16+
17+
Malformed scripts, either in search templates, ingest pipelines or search
18+
requests, return `400 - Bad request` while they would previously return
19+
`500 - Internal Server Error`. This also applies for stored scripts.

docs/reference/migration/migrate_7_0/search.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ The Search API returns `400 - Bad request` while it would previously return
4343
* the number of slices is too large
4444
* keep alive for scroll is too large
4545
* number of filters in the adjacency matrix aggregation is too large
46-
46+
* script compilation errors
4747

4848
==== Scroll queries cannot use the `request_cache` anymore
4949

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
package org.elasticsearch.script.mustache;
2020

2121
import com.github.mustachejava.Mustache;
22+
import com.github.mustachejava.MustacheException;
2223
import com.github.mustachejava.MustacheFactory;
2324

24-
import java.io.StringReader;
2525
import org.apache.logging.log4j.Logger;
2626
import org.apache.logging.log4j.message.ParameterizedMessage;
2727
import org.apache.logging.log4j.util.Supplier;
@@ -31,12 +31,15 @@
3131
import org.elasticsearch.script.Script;
3232
import org.elasticsearch.script.ScriptContext;
3333
import org.elasticsearch.script.ScriptEngine;
34+
import org.elasticsearch.script.ScriptException;
3435
import org.elasticsearch.script.TemplateScript;
3536

3637
import java.io.Reader;
38+
import java.io.StringReader;
3739
import java.io.StringWriter;
3840
import java.security.AccessController;
3941
import java.security.PrivilegedAction;
42+
import java.util.Collections;
4043
import java.util.Map;
4144

4245
/**
@@ -66,9 +69,14 @@ public <T> T compile(String templateName, String templateSource, ScriptContext<T
6669
}
6770
final MustacheFactory factory = createMustacheFactory(options);
6871
Reader reader = new StringReader(templateSource);
69-
Mustache template = factory.compile(reader, "query-template");
70-
TemplateScript.Factory compiled = params -> new MustacheExecutableScript(template, params);
71-
return context.factoryClazz.cast(compiled);
72+
try {
73+
Mustache template = factory.compile(reader, "query-template");
74+
TemplateScript.Factory compiled = params -> new MustacheExecutableScript(template, params);
75+
return context.factoryClazz.cast(compiled);
76+
} catch (MustacheException ex) {
77+
throw new ScriptException(ex.getMessage(), ex, Collections.emptyList(), templateSource, NAME);
78+
}
79+
7280
}
7381

7482
private CustomMustacheFactory createMustacheFactory(Map<String, String> options) {

modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/MustacheTests.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
*/
1919
package org.elasticsearch.script.mustache;
2020

21+
import org.elasticsearch.common.bytes.BytesReference;
22+
import org.elasticsearch.common.xcontent.XContentBuilder;
23+
import org.elasticsearch.common.xcontent.XContentHelper;
24+
import org.elasticsearch.script.ScriptEngine;
25+
import org.elasticsearch.script.ScriptException;
26+
import org.elasticsearch.script.TemplateScript;
27+
import org.elasticsearch.test.ESTestCase;
28+
import org.hamcrest.Matcher;
29+
2130
import java.net.URLEncoder;
2231
import java.nio.charset.StandardCharsets;
2332
import java.util.Arrays;
@@ -29,15 +38,6 @@
2938
import java.util.Map;
3039
import java.util.Set;
3140

32-
import com.github.mustachejava.MustacheException;
33-
import org.elasticsearch.common.bytes.BytesReference;
34-
import org.elasticsearch.common.xcontent.XContentBuilder;
35-
import org.elasticsearch.common.xcontent.XContentHelper;
36-
import org.elasticsearch.script.ScriptEngine;
37-
import org.elasticsearch.script.TemplateScript;
38-
import org.elasticsearch.test.ESTestCase;
39-
import org.hamcrest.Matcher;
40-
4141
import static java.util.Collections.singleton;
4242
import static java.util.Collections.singletonMap;
4343
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@@ -225,11 +225,17 @@ public void testSimpleListToJSON() throws Exception {
225225
}
226226

227227
public void testsUnsupportedTagsToJson() {
228-
MustacheException e = expectThrows(MustacheException.class, () -> compile("{{#toJson}}{{foo}}{{bar}}{{/toJson}}"));
228+
final String script = "{{#toJson}}{{foo}}{{bar}}{{/toJson}}";
229+
ScriptException e = expectThrows(ScriptException.class, () -> compile(script));
229230
assertThat(e.getMessage(), containsString("Mustache function [toJson] must contain one and only one identifier"));
231+
assertEquals(MustacheScriptEngine.NAME, e.getLang());
232+
assertEquals(script, e.getScript());
230233

231-
e = expectThrows(MustacheException.class, () -> compile("{{#toJson}}{{/toJson}}"));
234+
final String script2 = "{{#toJson}}{{/toJson}}";
235+
e = expectThrows(ScriptException.class, () -> compile(script2));
232236
assertThat(e.getMessage(), containsString("Mustache function [toJson] must contain one and only one identifier"));
237+
assertEquals(MustacheScriptEngine.NAME, e.getLang());
238+
assertEquals(script2, e.getScript());
233239
}
234240

235241
public void testEmbeddedToJSON() throws Exception {
@@ -312,11 +318,17 @@ public void testJoinWithToJson() {
312318
}
313319

314320
public void testsUnsupportedTagsJoin() {
315-
MustacheException e = expectThrows(MustacheException.class, () -> compile("{{#join}}{{/join}}"));
321+
final String script = "{{#join}}{{/join}}";
322+
ScriptException e = expectThrows(ScriptException.class, () -> compile(script));
316323
assertThat(e.getMessage(), containsString("Mustache function [join] must contain one and only one identifier"));
324+
assertEquals(MustacheScriptEngine.NAME, e.getLang());
325+
assertEquals(script, e.getScript());
317326

318-
e = expectThrows(MustacheException.class, () -> compile("{{#join delimiter='a'}}{{/join delimiter='b'}}"));
327+
final String script2 = "{{#join delimiter='a'}}{{/join delimiter='b'}}";
328+
e = expectThrows(ScriptException.class, () -> compile(script2));
319329
assertThat(e.getMessage(), containsString("Mismatched start/end tags"));
330+
assertEquals(MustacheScriptEngine.NAME, e.getLang());
331+
assertEquals(script2, e.getScript());
320332
}
321333

322334
public void testJoinWithCustomDelimiter() {

modules/lang-painless/src/test/resources/rest-api-spec/test/painless/16_update2.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
id: "non_existing"
3636

3737
- do:
38-
catch: request
38+
catch: bad_request
3939
put_script:
4040
id: "1"
4141
context: "search"

modules/lang-painless/src/test/resources/rest-api-spec/test/painless/20_scriptfield.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ setup:
133133
---
134134
"Scripted Field with script error":
135135
- do:
136-
catch: request
136+
catch: bad_request
137137
search:
138138
body:
139139
script_fields:

modules/reindex/src/test/resources/rest-api-spec/test/reindex/35_search_failures.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
indices.refresh: {}
1818

1919
- do:
20-
catch: request
20+
catch: bad_request
2121
reindex:
2222
body:
2323
source:

modules/reindex/src/test/resources/rest-api-spec/test/reindex/85_scripting.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@
446446
indices.refresh: {}
447447

448448
- do:
449-
catch: request
449+
catch: bad_request
450450
reindex:
451451
refresh: true
452452
body:

modules/reindex/src/test/resources/rest-api-spec/test/update_by_query/35_search_failure.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
indices.refresh: {}
1818

1919
- do:
20-
catch: request
20+
catch: bad_request
2121
update_by_query:
2222
index: source
2323
body:

0 commit comments

Comments
 (0)