Skip to content

Commit 294dd8f

Browse files
Fix CSV/RAW outputting wrong format (#279)
* Fixed bug where CSV/RAW outputs as JSON rather than plain text Signed-off-by: Matthew Wells <[email protected]>
1 parent a417aed commit 294dd8f

File tree

11 files changed

+113
-14
lines changed

11 files changed

+113
-14
lines changed

integ-test/src/test/java/org/opensearch/sql/sql/CsvFormatIT.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
package org.opensearch.sql.sql;
88

99
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_CSV_SANITIZE;
10+
import static org.opensearch.sql.protocol.response.format.FlatResponseFormatter.CONTENT_TYPE;
1011

1112
import java.io.IOException;
1213
import java.util.Locale;
14+
1315
import org.junit.Test;
16+
import org.opensearch.client.Request;
17+
import org.opensearch.client.Response;
1418
import org.opensearch.sql.common.utils.StringUtils;
1519
import org.opensearch.sql.legacy.SQLIntegTestCase;
1620

@@ -49,4 +53,17 @@ public void escapeSanitizeTest() {
4953
+ "\",Elinor\",\"Ratliff,,,\"%n"),
5054
result);
5155
}
56+
57+
@Test
58+
public void contentHeaderTest() throws IOException {
59+
String query = String.format(Locale.ROOT, "SELECT firstname, lastname FROM %s", TEST_INDEX_BANK_CSV_SANITIZE);
60+
String requestBody = makeRequest(query);
61+
62+
Request sqlRequest = new Request("POST", "/_plugins/_sql?format=csv");
63+
sqlRequest.setJsonEntity(requestBody);
64+
65+
Response response = client().performRequest(sqlRequest);
66+
67+
assertEquals(response.getEntity().getContentType(), CONTENT_TYPE);
68+
}
5269
}

integ-test/src/test/java/org/opensearch/sql/sql/RawFormatIT.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@
66

77
package org.opensearch.sql.sql;
88

9+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_CSV_SANITIZE;
910
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_RAW_SANITIZE;
11+
import static org.opensearch.sql.protocol.response.format.FlatResponseFormatter.CONTENT_TYPE;
1012

1113
import java.io.IOException;
1214
import java.util.Locale;
1315
import org.junit.Test;
16+
import org.opensearch.client.Request;
17+
import org.opensearch.client.Response;
1418
import org.opensearch.sql.common.utils.StringUtils;
1519
import org.opensearch.sql.legacy.SQLIntegTestCase;
1620

@@ -35,4 +39,16 @@ public void rawFormatWithPipeFieldTest() {
3539
result);
3640
}
3741

42+
@Test
43+
public void contentHeaderTest() throws IOException {
44+
String query = String.format(Locale.ROOT, "SELECT firstname, lastname FROM %s", TEST_INDEX_BANK_RAW_SANITIZE);
45+
String requestBody = makeRequest(query);
46+
47+
Request sqlRequest = new Request("POST", "/_plugins/_sql?format=raw");
48+
sqlRequest.setJsonEntity(requestBody);
49+
50+
Response response = client().performRequest(sqlRequest);
51+
52+
assertEquals(response.getEntity().getContentType(), CONTENT_TYPE);
53+
}
3854
}

integ-test/src/test/java/org/opensearch/sql/sql/SimpleQueryStringIT.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55

66
package org.opensearch.sql.sql;
77

8+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_CSV_SANITIZE;
89
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BEER;
10+
import static org.opensearch.sql.protocol.response.format.JsonResponseFormatter.CONTENT_TYPE;
911

1012
import java.io.IOException;
13+
import java.util.Locale;
14+
1115
import org.json.JSONObject;
1216
import org.junit.Test;
17+
import org.opensearch.client.Request;
18+
import org.opensearch.client.Response;
1319
import org.opensearch.sql.legacy.SQLIntegTestCase;
1420

1521
public class SimpleQueryStringIT extends SQLIntegTestCase {
@@ -61,4 +67,18 @@ public void verify_wildcard_test() throws IOException {
6167
var result = new JSONObject(executeQuery(query, "jdbc"));
6268
assertEquals(10, result.getInt("total"));
6369
}
70+
71+
@Test
72+
public void contentHeaderTest() throws IOException {
73+
String query = "SELECT Id FROM " + TEST_INDEX_BEER
74+
+ " WHERE simple_query_string([\\\"Tags\\\" ^ 1.5, Title, 'Body' 4.2], 'taste')";
75+
String requestBody = makeRequest(query);
76+
77+
Request sqlRequest = new Request("POST", "/_plugins/_sql");
78+
sqlRequest.setJsonEntity(requestBody);
79+
80+
Response response = client().performRequest(sqlRequest);
81+
82+
assertEquals(response.getEntity().getContentType(), CONTENT_TYPE);
83+
}
6484
}

legacy/src/main/java/org/opensearch/sql/legacy/plugin/RestSQLQueryAction.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,16 @@ public void onFailure(Exception e) {
141141

142142
private ResponseListener<ExplainResponse> createExplainResponseListener(
143143
RestChannel channel, BiConsumer<RestChannel, Exception> errorHandler) {
144-
return new ResponseListener<ExplainResponse>() {
144+
return new ResponseListener<>() {
145145
@Override
146146
public void onResponse(ExplainResponse response) {
147-
sendResponse(channel, OK, new JsonResponseFormatter<ExplainResponse>(PRETTY) {
147+
JsonResponseFormatter<ExplainResponse> formatter = new JsonResponseFormatter<>(PRETTY) {
148148
@Override
149149
protected Object buildJsonObject(ExplainResponse response) {
150150
return response;
151151
}
152-
}.format(response));
152+
};
153+
sendResponse(channel, OK, formatter.format(response), formatter.contentType());
153154
}
154155

155156
@Override
@@ -180,7 +181,7 @@ private ResponseListener<QueryResponse> createQueryResponseListener(
180181
public void onResponse(QueryResponse response) {
181182
sendResponse(channel, OK,
182183
formatter.format(new QueryResult(response.getSchema(), response.getResults(),
183-
response.getCursor())));
184+
response.getCursor())), formatter.contentType());
184185
}
185186

186187
@Override
@@ -190,9 +191,9 @@ public void onFailure(Exception e) {
190191
};
191192
}
192193

193-
private void sendResponse(RestChannel channel, RestStatus status, String content) {
194+
private void sendResponse(RestChannel channel, RestStatus status, String content, String contentType) {
194195
channel.sendResponse(new BytesRestResponse(
195-
status, "application/json; charset=UTF-8", content));
196+
status, contentType, content));
196197
}
197198

198199
private static void logAndPublishMetrics(Exception e) {

protocol/src/main/java/org/opensearch/sql/protocol/response/format/FlatResponseFormatter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ public abstract class FlatResponseFormatter implements ResponseFormatter<QueryRe
2323
private static final String INTERLINE_SEPARATOR = System.lineSeparator();
2424
private static final Set<String> SENSITIVE_CHAR = ImmutableSet.of("=", "+", "-", "@");
2525

26+
public static final String CONTENT_TYPE = "plain/text; charset=UTF-8";
27+
2628
private boolean sanitize = false;
2729

2830
public FlatResponseFormatter(String seperator, boolean sanitize) {
2931
this.INLINE_SEPARATOR = seperator;
3032
this.sanitize = sanitize;
3133
}
3234

35+
public String contentType() {
36+
return CONTENT_TYPE;
37+
}
38+
3339
@Override
3440
public String format(QueryResult response) {
3541
FlatResult result = new FlatResult(response, sanitize);

protocol/src/main/java/org/opensearch/sql/protocol/response/format/JsonResponseFormatter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public enum Style {
3636
*/
3737
private final Style style;
3838

39+
public static final String CONTENT_TYPE = "application/json; charset=UTF-8";
40+
3941
@Override
4042
public String format(R response) {
4143
return jsonify(buildJsonObject(response));
@@ -47,6 +49,10 @@ public String format(Throwable t) {
4749
(style == PRETTY) ? prettyFormat(t) : compactFormat(t));
4850
}
4951

52+
public String contentType() {
53+
return CONTENT_TYPE;
54+
}
55+
5056
/**
5157
* Build JSON object to generate response json string.
5258
*

protocol/src/main/java/org/opensearch/sql/protocol/response/format/ResponseFormatter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ public interface ResponseFormatter<R> {
2727
*/
2828
String format(Throwable t);
2929

30+
/**
31+
* Getter for the content type header of the response.
32+
*
33+
* @return string
34+
*/
35+
String contentType();
36+
3037
}

protocol/src/test/java/org/opensearch/sql/protocol/response/format/CommandResponseFormatterTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import static org.opensearch.sql.data.model.ExprValueUtils.tupleValue;
1111
import static org.opensearch.sql.data.type.ExprCoreType.INTEGER;
1212
import static org.opensearch.sql.data.type.ExprCoreType.STRING;
13+
import static org.opensearch.sql.protocol.response.format.JsonResponseFormatter.CONTENT_TYPE;
1314
import static org.opensearch.sql.protocol.response.format.JsonResponseFormatter.Style.PRETTY;
1415

1516
import com.google.common.collect.ImmutableList;
@@ -56,4 +57,10 @@ public void formats_error_as_default_formatter() {
5657
assertEquals(new JdbcResponseFormatter(PRETTY).format(exception),
5758
new CommandResponseFormatter().format(exception));
5859
}
60+
61+
@Test
62+
void testContentType() {
63+
var formatter = new CommandResponseFormatter();
64+
assertEquals(formatter.contentType(), CONTENT_TYPE);
65+
}
5966
}

protocol/src/test/java/org/opensearch/sql/protocol/response/format/CsvResponseFormatterTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import static org.opensearch.sql.data.model.ExprValueUtils.tupleValue;
1515
import static org.opensearch.sql.data.type.ExprCoreType.INTEGER;
1616
import static org.opensearch.sql.data.type.ExprCoreType.STRING;
17+
import static org.opensearch.sql.protocol.response.format.FlatResponseFormatter.CONTENT_TYPE;
1718

1819
import com.google.common.collect.ImmutableList;
1920
import com.google.common.collect.ImmutableMap;
@@ -130,4 +131,9 @@ void replaceNullValues() {
130131
assertEquals(format(expected), formatter.format(response));
131132
}
132133

134+
@Test
135+
void testContentType() {
136+
assertEquals(formatter.contentType(), CONTENT_TYPE);
137+
}
138+
133139
}

protocol/src/test/java/org/opensearch/sql/protocol/response/format/RawResponseFormatterTest.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import static org.opensearch.sql.data.model.ExprValueUtils.tupleValue;
1515
import static org.opensearch.sql.data.type.ExprCoreType.INTEGER;
1616
import static org.opensearch.sql.data.type.ExprCoreType.STRING;
17+
import static org.opensearch.sql.protocol.response.format.FlatResponseFormatter.CONTENT_TYPE;
1718

1819
import com.google.common.collect.ImmutableList;
1920
import com.google.common.collect.ImmutableMap;
@@ -27,7 +28,7 @@
2728
* Unit test for {@link FlatResponseFormatter}.
2829
*/
2930
public class RawResponseFormatterTest {
30-
private FlatResponseFormatter rawFormater = new RawResponseFormatter();
31+
private FlatResponseFormatter rawFormatter = new RawResponseFormatter();
3132

3233
@Test
3334
void formatResponse() {
@@ -38,7 +39,7 @@ void formatResponse() {
3839
tupleValue(ImmutableMap.of("name", "John", "age", 20)),
3940
tupleValue(ImmutableMap.of("name", "Smith", "age", 30))));
4041
String expected = "name|age%nJohn|20%nSmith|30";
41-
assertEquals(format(expected), rawFormater.format(response));
42+
assertEquals(format(expected), rawFormatter.format(response));
4243
}
4344

4445
@Test
@@ -53,7 +54,7 @@ void sanitizeHeaders() {
5354
"=firstname", "John", "+lastname", "Smith", "-city", "Seattle", "@age", 20))));
5455
String expected = "=firstname|+lastname|-city|@age%n"
5556
+ "John|Smith|Seattle|20";
56-
assertEquals(format(expected), rawFormater.format(response));
57+
assertEquals(format(expected), rawFormatter.format(response));
5758
}
5859

5960
@Test
@@ -74,7 +75,7 @@ void sanitizeData() {
7475
+ "-Seattle%n"
7576
+ "@Seattle%n"
7677
+ "Seattle=";
77-
assertEquals(format(expected), rawFormater.format(response));
78+
assertEquals(format(expected), rawFormatter.format(response));
7879
}
7980

8081
@Test
@@ -86,15 +87,15 @@ void quoteIfRequired() {
8687
tupleValue(ImmutableMap.of("na|me", "John|Smith", "||age", "30|||"))));
8788
String expected = "\"na|me\"|\"||age\"%n"
8889
+ "\"John|Smith\"|\"30|||\"";
89-
assertEquals(format(expected), rawFormater.format(response));
90+
assertEquals(format(expected), rawFormatter.format(response));
9091
}
9192

9293
@Test
9394
void formatError() {
9495
Throwable t = new RuntimeException("This is an exception");
9596
String expected =
9697
"{\n \"type\": \"RuntimeException\",\n \"reason\": \"This is an exception\"\n}";
97-
assertEquals(expected, rawFormater.format(t));
98+
assertEquals(expected, rawFormatter.format(t));
9899
}
99100

100101
@Test
@@ -121,7 +122,7 @@ void senstiveCharater() {
121122
String expected = "city%n"
122123
+ "@Seattle%n"
123124
+ "++Seattle";
124-
assertEquals(format(expected), rawFormater.format(response));
125+
assertEquals(format(expected), rawFormatter.format(response));
125126
}
126127

127128
@Test
@@ -153,7 +154,12 @@ void replaceNullValues() {
153154
+ "John|Seattle%n"
154155
+ "|Seattle%n"
155156
+ "John|";
156-
assertEquals(format(expected), rawFormater.format(response));
157+
assertEquals(format(expected), rawFormatter.format(response));
158+
}
159+
160+
@Test
161+
void testContentType() {
162+
assertEquals(rawFormatter.contentType(), CONTENT_TYPE);
157163
}
158164

159165
}

0 commit comments

Comments
 (0)