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

io.camunda.identity.sdk.impl.rest.RestClient Maven / Gradle / Ivy

The newest version!
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
 * one or more contributor license agreements. Licensed under a proprietary license. See the
 * License.txt file for more information. You may not use this file except in compliance with the
 * proprietary license.
 */

package io.camunda.identity.sdk.impl.rest;

import static java.util.stream.Collectors.joining;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.camunda.identity.sdk.impl.rest.exception.RestException;
import io.camunda.identity.sdk.impl.rest.request.Request;
import java.io.IOException;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

public class RestClient {
  private final ObjectMapper mapper =
      new ObjectMapper()
          .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  private final HttpClient client;

  public RestClient() {
    this(HttpClient.newBuilder().proxy(ProxySelector.getDefault())
             .followRedirects(HttpClient.Redirect.NEVER).build());
  }

  RestClient(final HttpClient client) {
    this.client = client;
  }

  /**
   * Performs a request to Camunda Account REST API and returns the response body mapped to provided
   * object type.
   *
   * @param      the return type parameter
   * @param request the request to be performed
   * @return the response of the provided type
   * @throws RestException Rest request exception in case the request fails
   */
  public  T request(final Request request) {
    final TypeReference typeReference = request.getTypeReference();
    final HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();

    if (request.getParams().isEmpty()) {
      requestBuilder.uri(URI.create(request.getUrl()));
    } else {
      final String params = generateParamString(request.getParams());
      requestBuilder.uri(
          URI.create(
              request.getUrl().concat("?").concat(params)
          )
      );
    }

    if (request.getAuthentication() != null) {
      requestBuilder.header("Authorization", "Bearer " + request.getAuthentication());
    }

    if (request.getContentType() != null) {
      requestBuilder.header("Content-Type", request.getContentType().toString());
    }

    if (request.getBody() != null) {
      final String body;

      switch (request.getContentType()) {
        case X_WWW_URL_ENCODED:
          body = urlEncodedBody(request.getBody());
          break;
        case JSON:
        default:
          try {
            body = jsonBody(request.getBody());
          } catch (final JsonProcessingException e) {
            throw new RestException("body serialization failed", e);
          }
          break;
      }

      final HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(body);

      if (
          request.getHttpMethod() != null
          && request.getHttpMethod().equals(Request.HttpMethod.PUT)
      ) {
        requestBuilder.PUT(bodyPublisher);
      } else {
        requestBuilder.POST(bodyPublisher);
      }
    }

    final HttpRequest httpRequest = requestBuilder.build();
    final HttpResponse response = send(httpRequest);
    try {
      if (typeReference.getType() == Void.class) {
        return null;
      }
      return mapper.readValue(response.body().toString(), typeReference);
    } catch (final IOException e) {
      throw new RestException("response can not be mapped to provided type", e);
    }
  }

  private HttpResponse send(final HttpRequest request) {
    try {
      final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
      final int statusCode = response.statusCode();

      if (statusCode < 200 || statusCode > 299) {
        throw new RestException(String
                                    .format("request failed with status code '%s' and body '%s'",
                                            statusCode, response.body().toString()));
      }

      return response;
    } catch (final IOException | InterruptedException e) {
      throw new RestException("request failed", e);
    }
  }

  private String jsonBody(final Object body) throws JsonProcessingException {
    return mapper.writeValueAsString(body);
  }

  private String urlEncodedBody(final Object body) {
    final Map params = mapper.convertValue(body, Map.class);
    return params.keySet().stream()
        .map(key -> key + "=" + urlEncode(params.get(key)))
        .collect(joining("&"));
  }

  private String generateParamString(final Map params) {
    return params.entrySet()
        .stream()
        .map(entry -> urlEncode(entry.getKey())
            .concat("=")
            .concat(urlEncode(entry.getValue())))
        .collect(Collectors.joining("&"));
  }

  private String urlEncode(final String value) {
    return URLEncoder.encode(value, StandardCharsets.UTF_8);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy