Skip to content

Commit 618b4dd

Browse files
#13776: allow adding query parameters to RequestOptions
Signed-off-by: Oliver Lockwood <oliver.lockwood@cantab.net>
1 parent 66df930 commit 618b4dd

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

client/rest/src/main/java/org/opensearch/client/RequestOptions.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@
4040

4141
import java.util.ArrayList;
4242
import java.util.Collections;
43+
import java.util.HashMap;
4344
import java.util.List;
45+
import java.util.Map;
4446
import java.util.Objects;
47+
import java.util.stream.Collectors;
4548

4649
/**
4750
* The portion of an HTTP request to OpenSearch that can be
@@ -53,18 +56,21 @@ public final class RequestOptions {
5356
*/
5457
public static final RequestOptions DEFAULT = new Builder(
5558
Collections.emptyList(),
59+
Collections.emptyMap(),
5660
HeapBufferedResponseConsumerFactory.DEFAULT,
5761
null,
5862
null
5963
).build();
6064

6165
private final List<Header> headers;
66+
private final Map<String, String> queryParams;
6267
private final HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory;
6368
private final WarningsHandler warningsHandler;
6469
private final RequestConfig requestConfig;
6570

6671
private RequestOptions(Builder builder) {
6772
this.headers = Collections.unmodifiableList(new ArrayList<>(builder.headers));
73+
this.queryParams = Collections.unmodifiableMap(new HashMap<>(builder.queryParams));
6874
this.httpAsyncResponseConsumerFactory = builder.httpAsyncResponseConsumerFactory;
6975
this.warningsHandler = builder.warningsHandler;
7076
this.requestConfig = builder.requestConfig;
@@ -74,7 +80,7 @@ private RequestOptions(Builder builder) {
7480
* Create a builder that contains these options but can be modified.
7581
*/
7682
public Builder toBuilder() {
77-
return new Builder(headers, httpAsyncResponseConsumerFactory, warningsHandler, requestConfig);
83+
return new Builder(headers, queryParams, httpAsyncResponseConsumerFactory, warningsHandler, requestConfig);
7884
}
7985

8086
/**
@@ -84,6 +90,13 @@ public List<Header> getHeaders() {
8490
return headers;
8591
}
8692

93+
/**
94+
* Query parameters to attach to the request.
95+
*/
96+
public Map<String, String> getQueryParams() {
97+
return queryParams;
98+
}
99+
87100
/**
88101
* The {@link HttpAsyncResponseConsumerFactory} used to create one
89102
* {@link AsyncResponseConsumer} callback per retry. Controls how the
@@ -142,6 +155,12 @@ public String toString() {
142155
b.append(headers.get(h).toString());
143156
}
144157
}
158+
if (queryParams.size() > 0) {
159+
if (comma) b.append(", ");
160+
comma = true;
161+
b.append("queryParams=");
162+
b.append(queryParams.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(",")));
163+
}
145164
if (httpAsyncResponseConsumerFactory != HttpAsyncResponseConsumerFactory.DEFAULT) {
146165
if (comma) b.append(", ");
147166
comma = true;
@@ -170,6 +189,7 @@ public boolean equals(Object obj) {
170189

171190
RequestOptions other = (RequestOptions) obj;
172191
return headers.equals(other.headers)
192+
&& queryParams.equals(other.queryParams)
173193
&& httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory)
174194
&& Objects.equals(warningsHandler, other.warningsHandler);
175195
}
@@ -179,7 +199,7 @@ public boolean equals(Object obj) {
179199
*/
180200
@Override
181201
public int hashCode() {
182-
return Objects.hash(headers, httpAsyncResponseConsumerFactory, warningsHandler);
202+
return Objects.hash(headers, queryParams, httpAsyncResponseConsumerFactory, warningsHandler);
183203
}
184204

185205
/**
@@ -189,17 +209,20 @@ public int hashCode() {
189209
*/
190210
public static class Builder {
191211
private final List<Header> headers;
212+
private final Map<String, String> queryParams;
192213
private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory;
193214
private WarningsHandler warningsHandler;
194215
private RequestConfig requestConfig;
195216

196217
private Builder(
197218
List<Header> headers,
219+
Map<String, String> queryParams,
198220
HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory,
199221
WarningsHandler warningsHandler,
200222
RequestConfig requestConfig
201223
) {
202224
this.headers = new ArrayList<>(headers);
225+
this.queryParams = new HashMap<>();
203226
this.httpAsyncResponseConsumerFactory = httpAsyncResponseConsumerFactory;
204227
this.warningsHandler = warningsHandler;
205228
this.requestConfig = requestConfig;
@@ -226,6 +249,20 @@ public Builder addHeader(String name, String value) {
226249
return this;
227250
}
228251

252+
/**
253+
* Add the provided query parameter to the request.
254+
*
255+
* @param name the query parameter name
256+
* @param value the query parameter value
257+
* @throws NullPointerException if {@code name} or {@code value} is null.
258+
*/
259+
public Builder addQueryParam(String name, String value) {
260+
Objects.requireNonNull(name, "query parameter name cannot be null");
261+
Objects.requireNonNull(value, "query parameter value cannot be null");
262+
this.queryParams.put(name, value);
263+
return this;
264+
}
265+
229266
/**
230267
* Set the {@link HttpAsyncResponseConsumerFactory} used to create one
231268
* {@link AsyncResponseConsumer} callback per retry. Controls how the

client/rest/src/main/java/org/opensearch/client/RestClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ private class InternalRequest {
832832
InternalRequest(Request request) {
833833
this.request = request;
834834
Map<String, String> params = new HashMap<>(request.getParameters());
835+
params.putAll(request.getOptions().getQueryParams());
835836
// ignore is a special parameter supported by the clients, shouldn't be sent to es
836837
String ignoreString = params.remove("ignore");
837838
this.ignoreErrorCodes = getIgnoreErrorCodes(ignoreString, request.getMethod());

client/rest/src/test/java/org/opensearch/client/RequestOptionsTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939

4040
import java.util.ArrayList;
4141
import java.util.Collections;
42+
import java.util.HashMap;
4243
import java.util.List;
44+
import java.util.Map;
4345

4446
import static org.junit.Assert.assertEquals;
4547
import static org.junit.Assert.assertNotEquals;
@@ -90,6 +92,41 @@ public void testAddHeader() {
9092
}
9193
}
9294

95+
public void testAddQueryParam() {
96+
try {
97+
randomBuilder().addQueryParam(null, randomAsciiLettersOfLengthBetween(3, 10));
98+
fail("expected failure");
99+
} catch (NullPointerException e) {
100+
assertEquals("query parameter name cannot be null", e.getMessage());
101+
}
102+
103+
try {
104+
randomBuilder().addQueryParam(randomAsciiLettersOfLengthBetween(3, 10), null);
105+
fail("expected failure");
106+
} catch (NullPointerException e) {
107+
assertEquals("query parameter value cannot be null", e.getMessage());
108+
}
109+
110+
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
111+
int numQueryParams = between(0, 5);
112+
Map<String, String> queryParams = new HashMap<>();
113+
for (int i = 0; i < numQueryParams; i++) {
114+
String name = randomAsciiAlphanumOfLengthBetween(5, 10);
115+
String value = randomAsciiAlphanumOfLength(3);
116+
queryParams.put(name, value);
117+
builder.addQueryParam(name, value);
118+
}
119+
RequestOptions options = builder.build();
120+
assertEquals(queryParams, options.getQueryParams());
121+
122+
try {
123+
options.getQueryParams().put(randomAsciiAlphanumOfLengthBetween(5, 10), randomAsciiAlphanumOfLength(3));
124+
fail("expected failure");
125+
} catch (UnsupportedOperationException e) {
126+
assertNull(e.getMessage());
127+
}
128+
}
129+
93130
public void testSetHttpAsyncResponseConsumerFactory() {
94131
try {
95132
RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null);
@@ -145,6 +182,13 @@ static RequestOptions.Builder randomBuilder() {
145182
}
146183
}
147184

185+
if (randomBoolean()) {
186+
int queryParamCount = between(1, 5);
187+
for (int i = 0; i < queryParamCount; i++) {
188+
builder.addQueryParam(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
189+
}
190+
}
191+
148192
if (randomBoolean()) {
149193
builder.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(1));
150194
}

0 commit comments

Comments
 (0)