@@ -4,6 +4,7 @@ import com.algolia.utils.Requester;
4
4
import com.algolia.exceptions.*;
5
5
import com.algolia.utils.UserAgent;
6
6
import com.algolia.utils.JSON;
7
+ import com.algolia.utils.RequestOptions;
7
8
8
9
import okhttp3.*;
9
10
import okhttp3.internal.http.HttpMethod;
@@ -27,8 +28,7 @@ public class ApiClient {
27
28
private boolean debugging = false ;
28
29
private Map< String, String> defaultHeaderMap = new HashMap< String, String> ();
29
30
30
-
31
- private String appId, apiKey;
31
+ private String contentType;
32
32
33
33
private DateFormat dateFormat;
34
34
@@ -38,6 +38,8 @@ public class ApiClient {
38
38
* Constructor for ApiClient with custom Requester
39
39
*/
40
40
public ApiClient(String appId, String apiKey, Requester requester, String clientName, UserAgent.Segment[] segments) {
41
+ this.contentType = " application/json" ;
42
+
41
43
UserAgent ua = new UserAgent(" {{packageVersion}}" );
42
44
ua.addSegment(new UserAgent.Segment(clientName, " {{packageVersion}}" ));
43
45
if (segments != null) {
@@ -47,8 +49,11 @@ public class ApiClient {
47
49
}
48
50
setUserAgent(ua.toString());
49
51
50
- this.appId = appId;
51
- this.apiKey = apiKey;
52
+ defaultHeaderMap.put("X-Algolia-Application-Id", appId);
53
+ defaultHeaderMap.put("X-Algolia-API-Key", apiKey);
54
+ defaultHeaderMap.put("Accept", this.contentType);
55
+ defaultHeaderMap.put("Content-Type", this.contentType);
56
+
52
57
this.requester = requester;
53
58
}
54
59
@@ -189,22 +194,6 @@ public class ApiClient {
189
194
}
190
195
}
191
196
192
- /**
193
- * Check if the given MIME is a JSON MIME.
194
- * JSON MIME examples:
195
- * application/json
196
- * application/json; charset=UTF8
197
- * APPLICATION/JSON
198
- * application/vnd.company+json
199
- * " * / *" is also default to JSON
200
- * @param mime MIME (Multipurpose Internet Mail Extensions)
201
- * @return True if the given MIME is JSON, false otherwise.
202
- */
203
- public static boolean isJsonMime(String mime) {
204
- String jsonMime = " (?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$" ;
205
- return mime != null && (mime.matches(jsonMime) || mime.equals(" */*" ));
206
- }
207
-
208
197
/**
209
198
* Escape the given string to be used as URL query value.
210
199
*
@@ -220,29 +209,23 @@ public class ApiClient {
220
209
}
221
210
222
211
/**
223
- * Serialize the given Java object into request body according to the object's
224
- * class and the request Content-Type.
212
+ * Serialize the given Java object into request body according to the object's class and the
213
+ * request Content-Type.
225
214
*
226
215
* @param obj The Java object
227
- * @param contentType The request Content-Type
228
216
* @return The serialized request body
229
217
* @throws AlgoliaRuntimeException If fail to serialize the given object
230
218
*/
231
- public RequestBody serialize(Object obj, String contentType) throws AlgoliaRuntimeException {
232
- if (obj instanceof byte[]) {
233
- // Binary (byte array) body parameter support.
234
- return RequestBody.create((byte[]) obj, MediaType.parse(contentType));
235
- } else if (isJsonMime(contentType)) {
236
- String content;
237
- if (obj != null) {
238
- content = JSON.serialize(obj);
239
- } else {
240
- content = null;
241
- }
242
- return RequestBody.create(content, MediaType.parse(contentType));
243
- } else {
244
- throw new AlgoliaRuntimeException(" Content type \" " + contentType + " \" is not supported" );
245
- }
219
+ public RequestBody serialize(Object obj) throws AlgoliaRuntimeException {
220
+ String content;
221
+
222
+ if (obj != null) {
223
+ content = JSON.serialize(obj);
224
+ } else {
225
+ content = null;
226
+ }
227
+
228
+ return RequestBody.create(content, MediaType.parse(this.contentType));
246
229
}
247
230
248
231
/**
@@ -286,11 +269,12 @@ public class ApiClient {
286
269
* @param queryParams The query parameters
287
270
* @param body The request body object
288
271
* @param headerParams The header parameters
272
+ * @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
289
273
* @return The HTTP call
290
274
* @throws AlgoliaRuntimeException If fail to serialize the request body object
291
275
*/
292
- public Call buildCall(String path, String method, Map<String , String > queryParams, Object body, Map<String , String > headerParams) throws AlgoliaRuntimeException {
293
- Request request = buildRequest(path, method, queryParams, body, headerParams);
276
+ public Call buildCall(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, RequestOptions requestOptions ) throws AlgoliaRuntimeException {
277
+ Request request = buildRequest(path, method, queryParams, body, headerParams, requestOptions );
294
278
295
279
return requester.newCall(request);
296
280
}
@@ -303,37 +287,38 @@ public class ApiClient {
303
287
* @param queryParams The query parameters
304
288
* @param body The request body object
305
289
* @param headerParams The header parameters
290
+ * @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
306
291
* @return The HTTP request
307
292
* @throws AlgoliaRuntimeException If fail to serialize the request body object
308
293
*/
309
- public Request buildRequest(String path, String method, Map<String , String > queryParams, Object body, Map<String , String > headerParams) throws AlgoliaRuntimeException {
310
- headerParams.put(" X-Algolia-Application-Id" , this.appId);
311
- headerParams.put(" X-Algolia-API-Key" , this.apiKey);
312
- headerParams.put(" Accept" , " application/json" );
313
- headerParams.put(" Content-Type" , " application/json" );
314
-
315
- String contentType = " application/json" ;
316
- headerParams.put(" Accept" , contentType);
317
- headerParams.put(" Content-Type" , contentType);
318
-
319
- final String url = buildUrl(path, queryParams);
294
+ public Request buildRequest(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, RequestOptions requestOptions) throws AlgoliaRuntimeException {
295
+ boolean hasRequestOptions = requestOptions != null;
296
+ final String url = buildUrl(
297
+ path,
298
+ queryParams,
299
+ hasRequestOptions ? requestOptions.getExtraQueryParams() : null
300
+ );
320
301
final Request.Builder reqBuilder = new Request.Builder().url(url);
321
- processHeaderParams(headerParams, reqBuilder);
322
-
302
+ processHeaderParams(
303
+ headerParams,
304
+ hasRequestOptions ? requestOptions.getExtraHeaders() : null,
305
+ reqBuilder
306
+ );
307
+
323
308
RequestBody reqBody;
324
309
if (!HttpMethod.permitsRequestBody(method)) {
325
310
reqBody = null;
326
311
} else if (body == null) {
327
312
if (" DELETE" .equals(method)) {
328
- // allow calling DELETE without sending a request body
329
- reqBody = null;
313
+ // allow calling DELETE without sending a request body
314
+ reqBody = null;
330
315
} else {
331
- // use an empty request body (for POST, PUT and PATCH)
332
- reqBody = RequestBody.create(" " , MediaType.parse(contentType));
316
+ // use an empty request body (for POST, PUT and PATCH)
317
+ reqBody = RequestBody.create(" " , MediaType.parse(this. contentType));
333
318
}
334
- } else {
335
- reqBody = serialize(body, contentType );
336
- }
319
+ } else {
320
+ reqBody = serialize(body);
321
+ }
337
322
338
323
return reqBuilder.method(method, reqBody).build();
339
324
}
@@ -343,48 +328,80 @@ public class ApiClient {
343
328
*
344
329
* @param path The sub path
345
330
* @param queryParams The query parameters
331
+ * @param extraQueryParams The query parameters, coming from the requestOptions
346
332
* @return The full URL
347
333
*/
348
- public String buildUrl(String path, Map<String , String > queryParams) {
349
- final StringBuilder url = new StringBuilder();
334
+ public String buildUrl(String path, Map<String, String> queryParams, Map<String, String> extraQueryParams ) {
335
+ StringBuilder url = new StringBuilder();
350
336
351
337
//The real host will be assigned by the retry strategy
352
338
url.append(" http://temp.path" ).append(path);
353
339
354
- if (queryParams != null && ! queryParams.isEmpty()) {
355
- // support (constant ) query string in `path`, e.g. " /posts?draft=1"
356
- String prefix = path.contains(" ?" ) ? " &" : " ?" ;
357
- for (Entry< String, String> param : queryParams.entrySet()) {
358
- if (param.getValue() != null) {
359
- if (prefix != null) {
360
- url.append(prefix);
361
- prefix = null;
362
- } else {
363
- url.append(" &" );
364
- }
365
- String value = parameterToString(param.getValue());
366
- url.append(escapeString(param.getKey())).append("=").append(escapeString(value));
367
- }
340
+ url = parseQueryParameters(path, url, queryParams);
341
+ url = parseQueryParameters(path, url, extraQueryParams);
342
+
343
+ return url.toString();
344
+ }
345
+
346
+ /**
347
+ * Parses the given map of Query Parameters to a given URL.
348
+ *
349
+ * @param path The sub path
350
+ * @param url The url to add queryParams to
351
+ * @param queryParams The query parameters
352
+ * @return The URL
353
+ */
354
+ public StringBuilder parseQueryParameters(
355
+ String path,
356
+ StringBuilder url,
357
+ Map<String, String> queryParams
358
+ ) {
359
+ if (queryParams != null && !queryParams.isEmpty()) {
360
+ // support (constant) query string in `path`, e.g. " /posts?draft= 1"
361
+ String prefix = path.contains(" ?" ) ? " &" : " ?" ;
362
+ for (Entry<String, String> param : queryParams.entrySet()) {
363
+ if (param.getValue() != null) {
364
+ if (prefix != null) {
365
+ url.append(prefix);
366
+ prefix = null;
367
+ } else {
368
+ url.append(" &" );
368
369
}
370
+ String value = parameterToString(param.getValue());
371
+ url
372
+ .append(escapeString(param.getKey()))
373
+ .append(" =" )
374
+ .append(escapeString(value));
375
+ }
369
376
}
377
+ }
370
378
371
- return url.toString() ;
379
+ return url;
372
380
}
373
381
374
382
/**
375
383
* Set header parameters to the request builder, including default headers.
376
384
*
377
385
* @param headerParams Header parameters in the form of Map
386
+ * @param extraHeaderParams Header parameters in the form of Map, coming from RequestOptions
378
387
* @param reqBuilder Request.Builder
379
388
*/
380
- public void processHeaderParams(Map<String , String > headerParams, Request.Builder reqBuilder) {
389
+ public void processHeaderParams(Map<String, String> headerParams, Map<String, String> extraHeaderParams, Request.Builder reqBuilder) {
381
390
for (Entry<String, String> param : headerParams.entrySet()) {
382
- reqBuilder.header(param.getKey(), parameterToString(param.getValue()));
391
+ reqBuilder.header(param.getKey(), parameterToString(param.getValue()));
383
392
}
384
393
for (Entry<String, String> header : defaultHeaderMap.entrySet()) {
385
- if (! headerParams.containsKey(header.getKey())) {
386
- reqBuilder.header(header.getKey(), parameterToString(header.getValue()));
387
- }
394
+ if (!headerParams.containsKey(header.getKey())) {
395
+ reqBuilder.header(header.getKey(), parameterToString(header.getValue()));
396
+ }
397
+ }
398
+ if (extraHeaderParams != null) {
399
+ for (Entry<String, String> header : extraHeaderParams.entrySet()) {
400
+ reqBuilder.header(
401
+ header.getKey(),
402
+ parameterToString(header.getValue())
403
+ );
404
+ }
388
405
}
389
406
}
390
407
0 commit comments