algoliasearch/src/main/java/com/algolia/search/saas/AbstractClient.java
private byte[] _requestRaw(@NonNull Method m, @NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String json, @NonNull List<String> hostsArray, int connectTimeout, int readTimeout, @Nullable RequestOptions requestOptions) throws AlgoliaException {
        String requestMethod;
        List<Exception> errors = new ArrayList<>(hostsArray.size());
        // for each host
        for (String host : hostsArray) {
            switch (m) {
                case DELETE:
                    requestMethod = "DELETE";
                    break;
                case GET:
                    requestMethod = "GET";
                    break;
                case POST:
                    requestMethod = "POST";
                    break;
                case PUT:
                    requestMethod = "PUT";
                    break;
                default:
                    throw new IllegalArgumentException("Method " + m + " is not supported");
            }

            InputStream stream = null;
            HttpURLConnection hostConnection = null;
            try {
                // Compute final URL parameters.
                final Map<String, String> parameters = new HashMap<>();
                if (urlParameters != null) {
                    parameters.putAll(urlParameters);
                }
                if (requestOptions != null) {
                    parameters.putAll(requestOptions.urlParameters);
                }

                // Build URL.
                String urlString = "https://" + host + url;
                if (!parameters.isEmpty()) {
                    urlString += "?" + AbstractQuery.build(parameters);
                }
                URL hostURL = new URL(urlString);

                // Open connection.
                hostConnection = (HttpURLConnection) hostURL.openConnection();

                //set timeouts
                hostConnection.setRequestMethod(requestMethod);
                hostConnection.setConnectTimeout(connectTimeout);
                hostConnection.setReadTimeout(readTimeout);

                // Headers
                hostConnection.setRequestProperty("Accept-Encoding", "gzip");
                hostConnection.setRequestProperty("X-Algolia-Application-Id", this.applicationID);
                // If API key is too big, send it in the request's body (if applicable).
                if (this.apiKey != null && this.apiKey.length() > MAX_API_KEY_LENGTH && json != null) {
                    try {
                        final JSONObject body = new JSONObject(json);
                        body.put("apiKey", this.apiKey);
                        json = body.toString();
                    } catch (JSONException e) {
                        throw new AlgoliaException("Failed to patch JSON body");
                    }
                } else {
                    hostConnection.setRequestProperty("X-Algolia-API-Key", this.apiKey);
                }
                // Client-level headers
                for (Map.Entry<String, String> entry : this.headers.entrySet()) {
                    hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
                }
                // Request-level headers
                if (requestOptions != null) {
                    for (Map.Entry<String, String> entry : requestOptions.headers.entrySet()) {
                        hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
                    }
                }

                // set user agent
                hostConnection.setRequestProperty("User-Agent", userAgentRaw);

                // write JSON entity
                if (json != null) {
                    if (!(requestMethod.equals("PUT") || requestMethod.equals("POST"))) {
                        throw new IllegalArgumentException("Method " + m + " cannot enclose entity");
                    }
                    hostConnection.setRequestProperty("Content-type", "application/json; charset=UTF-8");
                    hostConnection.setDoOutput(true);
                    OutputStreamWriter writer = new OutputStreamWriter(hostConnection.getOutputStream(), "UTF-8");
                    writer.write(json);
                    writer.close();
                }

                // read response
                int code = hostConnection.getResponseCode();
                final boolean codeIsError = code / 100 != 2;
                stream = codeIsError ? hostConnection.getErrorStream() : hostConnection.getInputStream();
                // As per the official Java docs (not the Android docs):
                // - `getErrorStream()` may return null => we have to handle this case.
                //   See <https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html#getErrorStream()>.
                // - `getInputStream()` should never return null... but let's err on the side of caution.
                //   See <https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getInputStream()>.
                if (stream == null) {
                    throw new IOException(String.format("Null stream when reading connection (status %d)", code));
                }
                hostStatuses.put(host, new HostStatus(true));

                final byte[] rawResponse;
                String encoding = hostConnection.getContentEncoding();
                if (encoding != null && encoding.equals("gzip")) {
                    rawResponse = _toByteArray(new GZIPInputStream(stream));
                } else {
                    rawResponse = _toByteArray(stream);
                }

                // handle http errors
                if (codeIsError) {
                    if (code / 100 == 4) {
                        consumeQuietly(hostConnection);
                        throw new AlgoliaException(_getJSONObject(rawResponse).getString("message"), code);
                    } else {
                        consumeQuietly(hostConnection);
                        errors.add(new AlgoliaException(_toCharArray(stream), code));
                        continue;
                    }
                }
                return rawResponse;

            } catch (JSONException e) { // fatal
                consumeQuietly(hostConnection);
                throw new AlgoliaException("Invalid JSON returned by server", e);
            } catch (UnsupportedEncodingException e) { // fatal
                consumeQuietly(hostConnection);
                throw new AlgoliaException("Invalid encoding returned by server", e);
            } catch (IOException e) { // host error, continue on the next host
                hostStatuses.put(host, new HostStatus(false));
                consumeQuietly(hostConnection);
                errors.add(e);
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        String errorMessage = "All hosts failed: " + Arrays.toString(errors.toArray());
        // When several errors occurred, use the last one as the cause for the returned exception.
        Throwable lastError = errors.get(errors.size() - 1);
        throw new AlgoliaException(errorMessage, lastError);
    }
private byte[] _requestRaw(@NonNull Method m, @NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String json, @NonNull List<String> hostsArray, int connectTimeout, int readTimeout, @Nullable RequestOptions requestOptions) throws AlgoliaException {
        String requestMethod;
        List<Exception> errors = new ArrayList<>(hostsArray.size());
        // for each host
        for (String host : hostsArray) {
            switch (m) {
                case DELETE:
                    requestMethod = "DELETE";
                    break;
                case GET:
                    requestMethod = "GET";
                    break;
                case POST:
                    requestMethod = "POST";
                    break;
                case PUT:
                    requestMethod = "PUT";
                    break;
                default:
                    throw new IllegalArgumentException("Method " + m + " is not supported");
            }

            InputStream stream = null;
            HttpURLConnection hostConnection = null;
            try {
                // Compute final URL parameters.
                final Map<String, String> parameters = new HashMap<>();
                if (urlParameters != null) {
                    parameters.putAll(urlParameters);
                }
                if (requestOptions != null) {
                    parameters.putAll(requestOptions.urlParameters);
                }

                // Build URL.
                String urlString = "https://" + host + url;
                if (!parameters.isEmpty()) {
                    urlString += "?" + AbstractQuery.build(parameters);
                }
                URL hostURL = new URL(urlString);

                // Open connection.
                hostConnection = (HttpURLConnection) hostURL.openConnection();

                //set timeouts
                hostConnection.setRequestMethod(requestMethod);
                hostConnection.setConnectTimeout(connectTimeout);
                hostConnection.setReadTimeout(readTimeout);

                // Headers
                hostConnection.setRequestProperty("Accept-Encoding", "gzip");
                hostConnection.setRequestProperty("X-Algolia-Application-Id", this.applicationID);
                // If API key is too big, send it in the request's body (if applicable).
                if (this.apiKey != null && this.apiKey.length() > MAX_API_KEY_LENGTH && json != null) {
                    try {
                        final JSONObject body = new JSONObject(json);
                        body.put("apiKey", this.apiKey);
                        json = body.toString();
                    } catch (JSONException e) {
                        throw new AlgoliaException("Failed to patch JSON body");
                    }
                } else {
                    hostConnection.setRequestProperty("X-Algolia-API-Key", this.apiKey);
                }
                // Client-level headers
                for (Map.Entry<String, String> entry : this.headers.entrySet()) {
                    hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
                }
                // Request-level headers
                if (requestOptions != null) {
                    for (Map.Entry<String, String> entry : requestOptions.headers.entrySet()) {
                        hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
                    }
                }

                // set user agent
                hostConnection.setRequestProperty("User-Agent", userAgentRaw);

                // write JSON entity
                if (json != null) {
                    if (!(requestMethod.equals("PUT") || requestMethod.equals("POST"))) {
                        throw new IllegalArgumentException("Method " + m + " cannot enclose entity");
                    }
                    hostConnection.setRequestProperty("Content-type", "application/json; charset=UTF-8");
                    hostConnection.setDoOutput(true);
                    OutputStreamWriter writer = new OutputStreamWriter(hostConnection.getOutputStream(), "UTF-8");
                    writer.write(json);
                    writer.close();
                }

                // read response
                int code = hostConnection.getResponseCode();
                final boolean codeIsError = code / 100 != 2;
                stream = codeIsError ? hostConnection.getErrorStream() : hostConnection.getInputStream();
                // As per the official Java docs (not the Android docs):
                // - `getErrorStream()` may return null => we have to handle this case.
                //   See <https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html#getErrorStream()>.
                // - `getInputStream()` should never return null... but let's err on the side of caution.
                //   See <https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getInputStream()>.
                if (stream == null) {
                    throw new IOException(String.format("Null stream when reading connection (status %d)", code));
                }
                hostStatuses.put(host, new HostStatus(true));

                final byte[] rawResponse;
                String encoding = hostConnection.getContentEncoding();
                if (encoding != null && encoding.equals("gzip")) {
                    rawResponse = _toByteArray(new GZIPInputStream(stream));
                } else {
                    rawResponse = _toByteArray(stream);
                }

                // handle http errors
                if (codeIsError) {
                    if (code / 100 == 4) {
                        consumeQuietly(hostConnection);
                        throw new AlgoliaException(_getJSONObject(rawResponse).getString("message"), code);
                    } else {
                        consumeQuietly(hostConnection);
                        errors.add(new AlgoliaException(_toCharArray(stream), code));
                        continue;
                    }
                }
                return rawResponse;

            } catch (JSONException e) { // fatal
                consumeQuietly(hostConnection);
                throw new AlgoliaException("Invalid JSON returned by server", e);
            } catch (UnsupportedEncodingException e) { // fatal
                consumeQuietly(hostConnection);
                throw new AlgoliaException("Invalid encoding returned by server", e);
            } catch (IOException e) { // host error, continue on the next host
                hostStatuses.put(host, new HostStatus(false));
                consumeQuietly(hostConnection);
                errors.add(e);
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        String errorMessage = "All hosts failed: " + Arrays.toString(errors.toArray());
        // When several errors occurred, use the last one as the cause for the returned exception.
        Throwable lastError = errors.get(errors.size() - 1);
        throw new AlgoliaException(errorMessage, lastError);
    }
private byte [ ] _requestRaw ( @ NonNull Method m , @ NonNull String url , @ Nullable Map < String , String > urlParameters , @ Nullable String json , @ NonNull List < String > hostsArray , int connectTimeout , int readTimeout , @ Nullable RequestOptions requestOptions ) throws AlgoliaException { String requestMethod ; List < Exception > errors = new ArrayList <> ( hostsArray . size ( ) ) ; // for each host for ( String host : hostsArray ) { switch ( m ) { case DELETE : requestMethod = "DELETE" ; break ; case GET : requestMethod = "GET" ; break ; case POST : requestMethod = "POST" ; break ; case PUT : requestMethod = "PUT" ; break ; default : throw new IllegalArgumentException ( "Method " + m + " is not supported" ) ; } InputStream stream = null ; HttpURLConnection hostConnection = null ; try { // Compute final URL parameters. final Map < String , String > parameters = new HashMap <> ( ) ; if ( urlParameters != null ) { parameters . putAll ( urlParameters ) ; } if ( requestOptions != null ) { parameters . putAll ( requestOptions . urlParameters ) ; } // Build URL. String urlString = "https://" + host + url ; if ( ! parameters . isEmpty ( ) ) { urlString += "?" + AbstractQuery . build ( parameters ) ; } URL hostURL = new URL ( urlString ) ; // Open connection. hostConnection = ( HttpURLConnection ) hostURL . openConnection ( ) ; //set timeouts hostConnection . setRequestMethod ( requestMethod ) ; hostConnection . setConnectTimeout ( connectTimeout ) ; hostConnection . setReadTimeout ( readTimeout ) ; // Headers hostConnection . setRequestProperty ( "Accept-Encoding" , "gzip" ) ; hostConnection . setRequestProperty ( "X-Algolia-Application-Id" , this . applicationID ) ; // If API key is too big, send it in the request's body (if applicable). if ( this . apiKey != null && this . apiKey . length ( ) > MAX_API_KEY_LENGTH && json != null ) { try { final JSONObject body = new JSONObject ( json ) ; body . put ( "apiKey" , this . apiKey ) ; json = body . toString ( ) ; } catch ( JSONException e ) { throw new AlgoliaException ( "Failed to patch JSON body" ) ; } } else { hostConnection . setRequestProperty ( "X-Algolia-API-Key" , this . apiKey ) ; } // Client-level headers for ( Map . Entry < String , String > entry : this . headers . entrySet ( ) ) { hostConnection . setRequestProperty ( entry . getKey ( ) , entry . getValue ( ) ) ; } // Request-level headers if ( requestOptions != null ) { for ( Map . Entry < String , String > entry : requestOptions . headers . entrySet ( ) ) { hostConnection . setRequestProperty ( entry . getKey ( ) , entry . getValue ( ) ) ; } } // set user agent hostConnection . setRequestProperty ( "User-Agent" , userAgentRaw ) ; // write JSON entity if ( json != null ) { if ( ! ( requestMethod . equals ( "PUT" ) || requestMethod . equals ( "POST" ) ) ) { throw new IllegalArgumentException ( "Method " + m + " cannot enclose entity" ) ; } hostConnection . setRequestProperty ( "Content-type" , "application/json; charset=UTF-8" ) ; hostConnection . setDoOutput ( true ) ; OutputStreamWriter writer = new OutputStreamWriter ( hostConnection . getOutputStream ( ) , "UTF-8" ) ; writer . write ( json ) ; writer . close ( ) ; } // read response int code = hostConnection . getResponseCode ( ) ; final boolean codeIsError = code / 100 != 2 ; stream = codeIsError ? hostConnection . getErrorStream ( ) : hostConnection . getInputStream ( ) ; // As per the official Java docs (not the Android docs): // - `getErrorStream()` may return null => we have to handle this case. //   See <https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html#getErrorStream()>. // - `getInputStream()` should never return null... but let's err on the side of caution. //   See <https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getInputStream()>. if ( stream == null ) { throw new IOException ( String . format ( "Null stream when reading connection (status %d)" , code ) ) ; } hostStatuses . put ( host , new HostStatus ( true ) ) ; final byte [ ] rawResponse ; String encoding = hostConnection . getContentEncoding ( ) ; if ( encoding != null && encoding . equals ( "gzip" ) ) { rawResponse = _toByteArray ( new GZIPInputStream ( stream ) ) ; } else { rawResponse = _toByteArray ( stream ) ; } // handle http errors if ( codeIsError ) { if ( code / 100 == 4 ) { consumeQuietly ( hostConnection ) ; throw new AlgoliaException ( _getJSONObject ( rawResponse ) . getString ( "message" ) , code ) ; } else { consumeQuietly ( hostConnection ) ; errors . add ( new AlgoliaException ( _toCharArray ( stream ) , code ) ) ; continue ; } } return rawResponse ; } catch ( JSONException e ) { // fatal consumeQuietly ( hostConnection ) ; throw new AlgoliaException ( "Invalid JSON returned by server" , e ) ; } catch ( UnsupportedEncodingException e ) { // fatal consumeQuietly ( hostConnection ) ; throw new AlgoliaException ( "Invalid encoding returned by server" , e ) ; } catch ( IOException e ) { // host error, continue on the next host hostStatuses . put ( host , new HostStatus ( false ) ) ; consumeQuietly ( hostConnection ) ; errors . add ( e ) ; } finally { if ( stream != null ) { try { stream . close ( ) ; } catch ( IOException e ) { e . printStackTrace ( ) ; } } } } String errorMessage = "All hosts failed: " + Arrays . toString ( errors . toArray ( ) ) ; // When several errors occurred, use the last one as the cause for the returned exception. Throwable lastError = errors . get ( errors . size ( ) - 1 ) ; throw new AlgoliaException ( errorMessage , lastError ) ; }
Send the query according to parameters and returns its result as a JSONObject

@param m              HTTP Method to use
@param url            Endpoint URL, *without query string*. The query string is handled by `urlParameters`.
@param urlParameters  URL parameters
@param json           (optional) JSON body
@param hostsArray     array of hosts to try successively
@param connectTimeout maximum wait time to open connection
@param readTimeout    maximum time to read data on socket
@return a JSONObject containing the resulting data or error
@throws AlgoliaException in case of connection or data handling error
Send the query according to parameters and returns its result as a JSONObject