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

jp.co.bizreach.elasticsearch4s.HttpUtils.scala Maven / Gradle / Ivy

The newest version!
package jp.co.bizreach.elasticsearch4s

import java.nio.charset.StandardCharsets

import org.asynchttpclient.{AsyncCompletionHandler, AsyncHttpClient, AsyncHttpClientConfig, Response}
import org.asynchttpclient.Dsl._

import scala.concurrent._
import scala.collection.JavaConverters._
import scala.util.control.NonFatal
import retry._

class HttpResponseException(status: Int, headers: Seq[(String, String)], body: String)
  extends RuntimeException(
    s"HTTP response is bad. Response status: ${status}\n" +
    "---- headers ----\n" +
    headers.map { case (key, value) => s"${key}: ${value}" }.mkString("\n") + "\n" +
    "---- body ----\n" +
    body
  ){

  def this(response: Response) = {
    this(
      status  = response.getStatusCode,
      headers = response.getHeaders.entries().asScala.map { entry => (entry.getKey, entry.getValue) },
      body    = response.getResponseBody
    )
  }
}

object ContentType {
  val JSON = "application/json"
  val XNDJSON = "application/x-ndjson"
}

object HttpUtils {



  def createHttpClient(): AsyncHttpClient = {
    asyncHttpClient()
  }

  def createHttpClient(config: AsyncHttpClientConfig): AsyncHttpClient = {
    asyncHttpClient(config)
  }

  def closeHttpClient(httpClient: AsyncHttpClient): Unit = {
    httpClient.close()
  }

  def put(httpClient: AsyncHttpClient, url: String, json: String, contentType: String = ContentType.JSON)
         (implicit retryConfig: RetryConfig): String = {
    retryBlocking {
      val f = httpClient.preparePut(url).setHeader("Content-Type", contentType)
        .setBody(json.getBytes("UTF-8")).execute()
      val response = f.get()
      if (response.getStatusCode >= 200 && response.getStatusCode < 300){
        response.getResponseBody(StandardCharsets.UTF_8)
      } else {
        throw new HttpResponseException(response)
      }
    }
  }

  def putAsync(httpClient: AsyncHttpClient, url: String, json: String, contentType: String = ContentType.JSON)
              (implicit retryConfig: RetryConfig, retryManager: FutureRetryManager, ec: ExecutionContext): Future[String] = {
    retryFuture {
      withAsyncResultHandler { handler =>
        httpClient.preparePut(url).setHeader("Content-Type", contentType)
          .setBody(json.getBytes("UTF-8")).execute(handler)
      }
    }
  }

  def post(httpClient: AsyncHttpClient, url: String, json: String, contentType: String = ContentType.JSON)
          (implicit retryConfig: RetryConfig): String = {
    retryBlocking {
      val f = httpClient.preparePost(url).setHeader("Content-Type", contentType)
        .setBody(json.getBytes("UTF-8")).execute()
      val response = f.get()
      if (response.getStatusCode >= 200 && response.getStatusCode < 300) {
        response.getResponseBody(StandardCharsets.UTF_8)
      } else {
        throw new HttpResponseException(response)
      }
    }
  }

  def postAsync(httpClient: AsyncHttpClient, url: String, json: String, contentType: String = ContentType.JSON)
               (implicit retryConfig: RetryConfig, retryManager: FutureRetryManager, ec: ExecutionContext): Future[String] = {
    retryFuture {
      withAsyncResultHandler { handler =>
        httpClient.preparePost(url).setHeader("Content-Type", contentType)
          .setBody(json.getBytes("UTF-8")).execute(handler)
      }
    }
  }

  def get(httpClient: AsyncHttpClient, url: String)(implicit retryConfig: RetryConfig): String = {
    retryBlocking {
      val f = httpClient.prepareGet(url).execute()
      val response = f.get()
      if (response.getStatusCode >= 200 && response.getStatusCode < 300) {
        response.getResponseBody(StandardCharsets.UTF_8)
      } else {
        throw new HttpResponseException(response)
      }
    }
  }

  def getAsync(httpClient: AsyncHttpClient, url: String)
              (implicit retryConfig: RetryConfig, retryManager: FutureRetryManager, ec: ExecutionContext): Future[String] = {
    retryFuture {
      withAsyncResultHandler { handler =>
        httpClient.prepareGet(url).execute(handler)
      }
    }
  }

  def delete(httpClient: AsyncHttpClient, url: String, json: String = "", contentType: String = ContentType.JSON)
            (implicit retryConfig: RetryConfig): String = {
    retryBlocking {
      val builder = httpClient.prepareDelete(url)
      if (json.nonEmpty) {
        builder.setHeader("Content-Type", contentType).setBody(json.getBytes("UTF-8"))
      }
      val f = builder.execute()
      f.get().getResponseBody(StandardCharsets.UTF_8)
    }
  }

  def deleteAsync(httpClient: AsyncHttpClient, url: String, json: String = "", contentType: String = ContentType.JSON)
                 (implicit retryConfig: RetryConfig, retryManager: FutureRetryManager, ec: ExecutionContext): Future[String] = {
    retryFuture {
      withAsyncResultHandler { handler =>
        val builder = httpClient.prepareDelete(url)
        if (json.nonEmpty) {
          builder.setHeader("Content-Type", contentType).setBody(json.getBytes("UTF-8"))
        }
        builder.execute(handler)
      }
    }
  }

  private def withAsyncResultHandler(requestAsync: AsyncResultHandler => Unit): Future[String] = {
    try {
      val promise = Promise[String]()
      requestAsync(new AsyncResultHandler(promise))
      promise.future
    } catch {
      case NonFatal(th) => Future.failed(th)
    }
  }

  private class AsyncResultHandler(promise: Promise[String]) extends AsyncCompletionHandler[Unit] {
    override def onCompleted(response: Response): Unit = {
      try {
        if (response.getStatusCode >= 200 && response.getStatusCode < 300) {
          promise.success(response.getResponseBody(StandardCharsets.UTF_8))
        } else {
          promise.failure(new HttpResponseException(response))
        }
      } catch {
        case NonFatal(t) => promise.tryFailure(t)
      }
    }
    override def onThrowable(t: Throwable): Unit = {
      promise.failure(t)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy