All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.lucasepe.core.rest.Breezy Maven / Gradle / Ivy

package io.github.lucasepe.core.rest;

import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.*;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Breezy {
  private static final Logger LOG = Logger.getLogger(Breezy.class.getName());

  private static final String ROOT_PATH = "/";

  public static Function> invoke() {
    return (api) -> {

      for (Node node : api.nodes) {

        if (!node.shouldTry()) {
          LOG.log(Level.WARNING, String.format("node %1$s not ready", node));
          continue;
        }

        LOG.log(Level.FINE, String.format("trying node %1$s", node));

        final HttpUrl.Builder url = Objects.requireNonNull(HttpUrl.parse(node.getUrl())).newBuilder();
        url.encodedPath(Breezy.path().apply(api));

        final Map params = Breezy.queryParams().apply(api);
        for (Map.Entry entry : params.entrySet()) {
          url.addQueryParameter(entry.getKey(), entry.getValue());
        }

        LOG.log(Level.FINE, String.format("=> %1$s %2$s", api.query.verb, url));

        HttpRequest request = null;
        try {
          request = new HttpRequest(url.build().toString(), api.query.verb.toString());
          for (Map.Entry entry : api.headers.entrySet()) {
            request.header(entry.getKey(), entry.getValue());
          }

          if (api.query.hasBody()) {
            final String payload = api.alterBodyFunction.apply(api.query.getBody());
            LOG.log(Level.FINE, String.format("=> %1$s", payload));
            request.contentType(HttpRequest.CONTENT_TYPE_JSON);
            request.send(payload);
          }

          final int code = request.code();
          final String message = request.message();
          LOG.log(Level.FINEST, String.format("server response code: %1$d, message: %2$s", code, message));

          node.succeeded();

          final String body = request.body();
          LOG.log(Level.FINE, String.format("<= %1$s", body));

          if ((code >= 200) && (code < 300)) {
            return Optional.ofNullable(body);
          }

          throw new ApiException(code, message, body);

        } catch (HttpRequest.HttpRequestException err) {
          if (err.getCause() instanceof ConnectException) {
            LOG.log(Level.SEVERE, String.format("failed to reach url: %1$s", node), err);
            node.failed();
          } else if (err.getCause() instanceof UnknownHostException) {
            LOG.log(Level.SEVERE, String.format("invalid or unknown host: %1$s", node), err);
            node.failed();
          } else {
            throw err;
          }

        } finally {
          if (request != null) {
            request.disconnect();
          }
        }
      }

      throw new RuntimeException(
          String.format("could not connect to any of the nodes: %1$s", Arrays.toString(api.nodes)));
    };
  }

  public static Function path() {
    return (api) -> {
      if ((api == null) || api.query.uri.equals(ROOT_PATH)) {
        return ROOT_PATH;
      }

      final String format = api.query.uri.startsWith(ROOT_PATH) ? "http://localhost%1$s" : "http://localhost/%1$s";
      final HttpUrl url = HttpUrl.parse(String.format(format, api.query.uri));
      return (url != null) ? url.encodedPath() : ROOT_PATH;
    };
  }

  public static Function> queryParams() {
    return (api) -> {
      if ((api == null) || (api.query.uri.equals("/"))) {
        return Collections.emptyMap();
      }

      final String format = api.query.uri.startsWith(ROOT_PATH) ? "http://localhost%1$s" : "http://localhost/%1$s";
      final HttpUrl url = HttpUrl.parse(String.format(format, api.query.uri));
      if (url == null) {
        return Collections.emptyMap();
      }

      final Map result = new HashMap<>();

      final Set params = url.queryParameterNames();
      for (String name: params) {
        result.put(name, url.queryParameter(name));
      }

      return result;
    };
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy