org.http4s.client.Client Scala Examples
The following examples show how to use org.http4s.client.Client.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: DeploymentsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.apps.v1.{Deployment, DeploymentList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class DeploymentsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[DeploymentList], encoder: Encoder[Deployment], decoder: Decoder[Deployment] ) extends Listable[F, DeploymentList] { val resourceUri: Uri = uri"/apis" / "apps" / "v1" / "deployments" def namespace(namespace: String): NamespacedDeploymentsApi[F] = NamespacedDeploymentsApi(httpClient, config, namespace) } private[client] case class NamespacedDeploymentsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[Deployment], val resourceDecoder: Decoder[Deployment], val listDecoder: Decoder[DeploymentList] ) extends Creatable[F, Deployment] with Replaceable[F, Deployment] with Gettable[F, Deployment] with Listable[F, DeploymentList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, Deployment] { val resourceUri: Uri = uri"/apis" / "apps" / "v1" / "namespaces" / namespace / "deployments" }
Example 2
Source File: ReplicaSetsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.apps.v1.{ReplicaSet, ReplicaSetList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class ReplicaSetsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[ReplicaSetList], encoder: Encoder[ReplicaSet], decoder: Decoder[ReplicaSet] ) extends Listable[F, ReplicaSetList] { val resourceUri: Uri = uri"/apis" / "apps" / "v1" / "replicasets" def namespace(namespace: String): NamespacedReplicaSetsApi[F] = NamespacedReplicaSetsApi(httpClient, config, namespace) } private[client] case class NamespacedReplicaSetsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[ReplicaSet], val resourceDecoder: Decoder[ReplicaSet], val listDecoder: Decoder[ReplicaSetList] ) extends Creatable[F, ReplicaSet] with Replaceable[F, ReplicaSet] with Gettable[F, ReplicaSet] with Listable[F, ReplicaSetList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, ReplicaSet] { val resourceUri = uri"/apis" / "apps" / "v1" / "namespaces" / namespace / "replicasets" }
Example 3
Source File: StatefulSetsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.apps.v1.{StatefulSet, StatefulSetList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class StatefulSetsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[StatefulSetList], encoder: Encoder[StatefulSet], decoder: Decoder[StatefulSet] ) extends Listable[F, StatefulSetList] { val resourceUri: Uri = uri"/apis" / "apps" / "v1" / "statefulsets" def namespace(namespace: String): NamespacedStatefulSetsApi[F] = NamespacedStatefulSetsApi(httpClient, config, namespace) } private[client] case class NamespacedStatefulSetsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[StatefulSet], val resourceDecoder: Decoder[StatefulSet], val listDecoder: Decoder[StatefulSetList] ) extends Creatable[F, StatefulSet] with Replaceable[F, StatefulSet] with Gettable[F, StatefulSet] with Listable[F, StatefulSetList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, StatefulSet] { val resourceUri: Uri = uri"/apis" / "apps" / "v1" / "namespaces" / namespace / "statefulsets" }
Example 4
Source File: SecretsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import java.util.Base64 import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.core.v1.{Secret, SecretList} import org.http4s.{Status, Uri} import org.http4s.client.Client import org.http4s.implicits._ import scala.collection.compat._ private[client] case class SecretsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[SecretList], encoder: Encoder[Secret], decoder: Decoder[Secret] ) extends Listable[F, SecretList] { val resourceUri = uri"/api" / "v1" / "secrets" def namespace(namespace: String) = NamespacedSecretsApi(httpClient, config, namespace) } private[client] case class NamespacedSecretsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[Secret], val resourceDecoder: Decoder[Secret], val listDecoder: Decoder[SecretList] ) extends Creatable[F, Secret] with Replaceable[F, Secret] with Gettable[F, Secret] with Listable[F, SecretList] with Deletable[F] with GroupDeletable[F] with Watchable[F, Secret] { val resourceUri: Uri = uri"/api" / "v1" / "namespaces" / namespace / "secrets" def createEncode(resource: Secret): F[Status] = create(encode(resource)) def createOrUpdateEncode(resource: Secret): F[Status] = createOrUpdate(encode(resource)) private def encode(resource: Secret) = resource.copy(data = resource.data.map(_.view.mapValues(v => Base64.getEncoder.encodeToString(v.getBytes)).toMap)) }
Example 5
Source File: ConfigMapsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.core.v1.{ConfigMap, ConfigMapList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class ConfigMapsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[ConfigMapList], encoder: Encoder[ConfigMap], decoder: Decoder[ConfigMap] ) extends Listable[F, ConfigMapList] { val resourceUri: Uri = uri"/api" / "v1" / "configmaps" def namespace(namespace: String): NamespacedConfigMapsApi[F] = NamespacedConfigMapsApi(httpClient, config, namespace) } private[client] case class NamespacedConfigMapsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[ConfigMap], val resourceDecoder: Decoder[ConfigMap], val listDecoder: Decoder[ConfigMapList] ) extends Creatable[F, ConfigMap] with Replaceable[F, ConfigMap] with Gettable[F, ConfigMap] with Listable[F, ConfigMapList] with Deletable[F] with GroupDeletable[F] with Watchable[F, ConfigMap] { val resourceUri: Uri = uri"/api" / "v1" / "namespaces" / namespace / "configmaps" }
Example 6
Source File: NamespacesApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe.{Decoder, Encoder} import io.k8s.api.core.v1.{Namespace, NamespaceList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class NamespacesApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[NamespaceList], val resourceEncoder: Encoder[Namespace], val resourceDecoder: Decoder[Namespace] ) extends Creatable[F, Namespace] with Replaceable[F, Namespace] with Gettable[F, Namespace] with Listable[F, NamespaceList] with Deletable[F] with DeletableTerminated[F] with Watchable[F, Namespace] { protected val resourceUri: Uri = uri"/api" / "v1" / "namespaces" }
Example 7
Source File: PodDisruptionBudgetsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.policy.v1beta1.{PodDisruptionBudget, PodDisruptionBudgetList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class PodDisruptionBudgetsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[PodDisruptionBudgetList], encoder: Encoder[PodDisruptionBudget], decoder: Decoder[PodDisruptionBudget] ) extends Listable[F, PodDisruptionBudgetList] { val resourceUri: Uri = uri"/apis" / "policy" / "v1beta1" / "poddisruptionbudgets" def namespace(namespace: String): NamespacedPodDisruptionBudgetApi[F] = NamespacedPodDisruptionBudgetApi(httpClient, config, namespace) } private[client] case class NamespacedPodDisruptionBudgetApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[PodDisruptionBudget], val resourceDecoder: Decoder[PodDisruptionBudget], val listDecoder: Decoder[PodDisruptionBudgetList] ) extends Creatable[F, PodDisruptionBudget] with Replaceable[F, PodDisruptionBudget] with Gettable[F, PodDisruptionBudget] with Listable[F, PodDisruptionBudgetList] with Deletable[F] with GroupDeletable[F] with Watchable[F, PodDisruptionBudget] { val resourceUri: Uri = uri"/apis" / "policy" / "v1beta1" / "namespaces" / namespace / "poddisruptionbudgets" }
Example 8
Source File: CustomResourceDefinitionsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe.{Decoder, Encoder} import io.k8s.apiextensionsapiserver.pkg.apis.apiextensions.v1.{CustomResourceDefinition, CustomResourceDefinitionList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class CustomResourceDefinitionsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[CustomResourceDefinitionList], val resourceEncoder: Encoder[CustomResourceDefinition], val resourceDecoder: Decoder[CustomResourceDefinition] ) extends Creatable[F, CustomResourceDefinition] with Replaceable[F, CustomResourceDefinition] with Gettable[F, CustomResourceDefinition] with Listable[F, CustomResourceDefinitionList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, CustomResourceDefinition] { self => val resourceUri: Uri = uri"/apis" / "apiextensions.k8s.io" / "v1" / "customresourcedefinitions" override val watchResourceUri: Uri = uri"/apis" / "apiextensions.k8s.io" / "v1" / "watch" / "customresourcedefinitions" }
Example 9
Source File: ServiceAccountsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.core.v1.{ServiceAccount, ServiceAccountList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class ServiceAccountsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[ServiceAccountList], encoder: Encoder[ServiceAccount], decoder: Decoder[ServiceAccount] ) extends Listable[F, ServiceAccountList] { val resourceUri: Uri = uri"/api" / "v1" / "serviceaccounts" def namespace(namespace: String): NamespacedServiceAccountsApi[F] = NamespacedServiceAccountsApi(httpClient, config, namespace) } private[client] case class NamespacedServiceAccountsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[ServiceAccount], val resourceDecoder: Decoder[ServiceAccount], val listDecoder: Decoder[ServiceAccountList] ) extends Creatable[F, ServiceAccount] with Replaceable[F, ServiceAccount] with Gettable[F, ServiceAccount] with Listable[F, ServiceAccountList] with Deletable[F] with GroupDeletable[F] with Watchable[F, ServiceAccount] { val resourceUri: Uri = uri"/api" / "v1" / "namespaces" / namespace / "serviceaccounts" }
Example 10
Source File: HorizontalPodAutoscalersApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.autoscaling.v1.{HorizontalPodAutoscaler, HorizontalPodAutoscalerList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class HorizontalPodAutoscalersApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[HorizontalPodAutoscalerList], encoder: Encoder[HorizontalPodAutoscaler], decoder: Decoder[HorizontalPodAutoscaler] ) extends Listable[F, HorizontalPodAutoscalerList] { val resourceUri: Uri = uri"/apis" / "autoscaling" / "v1" / "horizontalpodautoscalers" def namespace(namespace: String): NamespacedHorizontalPodAutoscalersApi[F] = NamespacedHorizontalPodAutoscalersApi(httpClient, config, namespace) } private[client] case class NamespacedHorizontalPodAutoscalersApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[HorizontalPodAutoscaler], val resourceDecoder: Decoder[HorizontalPodAutoscaler], val listDecoder: Decoder[HorizontalPodAutoscalerList] ) extends Creatable[F, HorizontalPodAutoscaler] with Replaceable[F, HorizontalPodAutoscaler] with Gettable[F, HorizontalPodAutoscaler] with Listable[F, HorizontalPodAutoscalerList] with Deletable[F] with GroupDeletable[F] with Watchable[F, HorizontalPodAutoscaler] { val resourceUri: Uri = uri"/apis" / "autoscaling" / "v1" / "namespaces" / namespace / "horizontalpodautoscalers" }
Example 11
Source File: ServicesApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.core.v1.{Service, ServiceList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class ServicesApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[ServiceList], encoder: Encoder[Service], decoder: Decoder[Service] ) extends Listable[F, ServiceList] { val resourceUri: Uri = uri"/api" / "v1" / "services" def namespace(namespace: String): NamespacedServicesApi[F] = NamespacedServicesApi(httpClient, config, namespace) } private[client] case class NamespacedServicesApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[Service], val resourceDecoder: Decoder[Service], val listDecoder: Decoder[ServiceList] ) extends Creatable[F, Service] with Replaceable[F, Service] with Gettable[F, Service] with Listable[F, ServiceList] with Proxy[F] with Deletable[F] with GroupDeletable[F] with Watchable[F, Service] { val resourceUri: Uri = uri"/api" / "v1" / "namespaces" / namespace / "services" }
Example 12
Source File: JobsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.batch.v1.{Job, JobList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class JobsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[JobList], encoder: Encoder[Job], decoder: Decoder[Job] ) extends Listable[F, JobList] { val resourceUri: Uri = uri"/apis" / "batch" / "v1" / "jobs" def namespace(namespace: String): NamespacedJobsApi[F] = NamespacedJobsApi(httpClient, config, namespace) } private[client] case class NamespacedJobsApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[Job], val resourceDecoder: Decoder[Job], val listDecoder: Decoder[JobList] ) extends Creatable[F, Job] with Replaceable[F, Job] with Gettable[F, Job] with Listable[F, JobList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, Job] { val resourceUri: Uri = uri"/apis" / "batch" / "v1" / "namespaces" / namespace / "jobs" }
Example 13
Source File: IngressesApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ import io.k8s.api.networking.v1beta1.{Ingress, IngressList} private[client] case class IngressessApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[IngressList], encoder: Encoder[Ingress], decoder: Decoder[Ingress] ) extends Listable[F, IngressList] { val resourceUri: Uri = uri"/apis" / "extensions" / "v1beta1" / "ingresses" def namespace(namespace: String): NamespacedIngressesApi[F] = NamespacedIngressesApi(httpClient, config, namespace) } private[client] case class NamespacedIngressesApi[F[_]]( httpClient: Client[F], config: KubeConfig, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[Ingress], val resourceDecoder: Decoder[Ingress], val listDecoder: Decoder[IngressList] ) extends Creatable[F, Ingress] with Replaceable[F, Ingress] with Gettable[F, Ingress] with Listable[F, IngressList] with Deletable[F] with GroupDeletable[F] with Watchable[F, Ingress] { val resourceUri: Uri = uri"/apis" / "extensions" / "v1beta1" / "namespaces" / namespace / "ingresses" }
Example 14
Source File: KubernetesClient.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client import java.net.http.HttpClient import cats.effect._ import com.goyeau.kubernetes.client.api._ import com.goyeau.kubernetes.client.crd.{CrdContext, CustomResource, CustomResourceList} import com.goyeau.kubernetes.client.util.SslContexts import io.circe.{Decoder, Encoder} import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import org.http4s.client.jdkhttpclient.JdkWSClient import scala.concurrent.ExecutionContext case class KubernetesClient[F[_]: ConcurrentEffect: ContextShift](httpClient: Client[F], config: KubeConfig) { lazy val namespaces = NamespacesApi(httpClient, config) lazy val pods = PodsApi( httpClient, JdkWSClient[F](HttpClient.newBuilder().sslContext(SslContexts.fromConfig(config)).build()), config ) lazy val jobs = JobsApi(httpClient, config) lazy val cronJobs = CronJobsApi(httpClient, config) lazy val deployments = DeploymentsApi(httpClient, config) lazy val statefulSets = StatefulSetsApi(httpClient, config) lazy val replicaSets = ReplicaSetsApi(httpClient, config) lazy val services = ServicesApi(httpClient, config) lazy val serviceAccounts = ServiceAccountsApi(httpClient, config) lazy val configMaps = ConfigMapsApi(httpClient, config) lazy val secrets = SecretsApi(httpClient, config) lazy val horizontalPodAutoscalers = HorizontalPodAutoscalersApi(httpClient, config) lazy val podDisruptionBudgets = PodDisruptionBudgetsApi(httpClient, config) lazy val customResourceDefinitions = CustomResourceDefinitionsApi(httpClient, config) lazy val ingresses = IngressessApi(httpClient, config) def customResources[A: Encoder: Decoder, B: Encoder: Decoder](context: CrdContext)(implicit listDecoder: Decoder[CustomResourceList[A, B]], encoder: Encoder[CustomResource[A, B]], decoder: Decoder[CustomResource[A, B]] ) = CustomResourcesApi[F, A, B](httpClient, config, context) } object KubernetesClient { def apply[F[_]: ConcurrentEffect: ContextShift](config: KubeConfig): Resource[F, KubernetesClient[F]] = BlazeClientBuilder[F](ExecutionContext.global, Option(SslContexts.fromConfig(config))).resource .map(httpClient => apply(httpClient, config)) def apply[F[_]: ConcurrentEffect: ContextShift](config: F[KubeConfig]): Resource[F, KubernetesClient[F]] = Resource.liftF(config).flatMap(apply(_)) }
Example 15
Source File: Creatable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import scala.language.reflectiveCalls import cats.implicits._ import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.util.CirceEntityCodec._ import com.goyeau.kubernetes.client.util.EnrichedStatus import io.circe._ import io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta import org.http4s._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.http4s.headers.`Content-Type` import org.http4s.Method._ private[client] trait Creatable[F[_], Resource <: { def metadata: Option[ObjectMeta] }] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri implicit protected def resourceEncoder: Encoder[Resource] def create(resource: Resource): F[Status] = httpClient.fetch(POST(resource, config.server.resolve(resourceUri), config.authorization.toSeq: _*))( EnrichedStatus[F] ) def createOrUpdate(resource: Resource): F[Status] = { val fullResourceUri = config.server.resolve(resourceUri) / resource.metadata.get.name.get def update = httpClient.fetch( PATCH( resource, fullResourceUri, `Content-Type`(MediaType.application.`merge-patch+json`) +: config.authorization.toSeq: _* ) )(EnrichedStatus[F]) httpClient .fetch(GET(fullResourceUri, config.authorization.toSeq: _*))(EnrichedStatus.apply[F]) .flatMap { case status if status.isSuccess => update case Status.NotFound => create(resource).recoverWith { case Status.Conflict => update } } } }
Example 16
Source File: Deletable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.util.CirceEntityCodec._ import com.goyeau.kubernetes.client.util.EnrichedStatus import io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions import org.http4s._ import org.http4s.Method._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl private[client] trait Deletable[F[_]] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri def delete(name: String, deleteOptions: Option[DeleteOptions] = None): F[Status] = httpClient.fetch( Request( DELETE, config.server.resolve(resourceUri) / name, headers = Headers(config.authorization.toList), body = deleteOptions.fold[EntityBody[F]](EmptyBody)(implicitly[EntityEncoder[F, DeleteOptions]].toEntity(_).body) ) )(EnrichedStatus[F]) }
Example 17
Source File: Proxy.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import org.http4s._ import org.http4s.dsl.impl.Path import org.http4s.client.Client import org.http4s.EntityDecoder import org.http4s.headers.`Content-Type` private[client] trait Proxy[F[_]] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri def proxy( name: String, method: Method, path: Path, contentType: `Content-Type` = `Content-Type`(MediaType.text.plain), data: Option[String] = None ): F[String] = httpClient.expect[String]( Request( method, config.server.resolve(resourceUri) / name / s"proxy$path", headers = Headers(config.authorization.toList), body = data.fold[EntityBody[F]](EmptyBody)( implicitly[EntityEncoder[F, String]].withContentType(contentType).toEntity(_).body ) ) )(EntityDecoder.text) }
Example 18
Source File: Replaceable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import scala.language.reflectiveCalls import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.util.CirceEntityCodec._ import com.goyeau.kubernetes.client.util.EnrichedStatus import io.circe._ import io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta import org.http4s._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.http4s.Method._ private[client] trait Replaceable[F[_], Resource <: { def metadata: Option[ObjectMeta] }] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri implicit protected def resourceEncoder: Encoder[Resource] def replace(resource: Resource): F[Status] = httpClient.fetch( PUT( resource, config.server.resolve(resourceUri) / resource.metadata.get.name.get, config.authorization.toSeq: _* ) )(EnrichedStatus[F]) }
Example 19
Source File: GroupDeletable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.util.EnrichedStatus import com.goyeau.kubernetes.client.util.Uris.addLabels import org.http4s._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.http4s.Method._ private[client] trait GroupDeletable[F[_]] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri @deprecated("Use deleteAll() instead", "0.4.0") lazy val delete: F[Status] = deleteAll() def deleteAll(labels: Map[String, String] = Map.empty): F[Status] = { val uri = addLabels(labels, config.server.resolve(resourceUri)) httpClient.fetch(DELETE(uri, config.authorization.toSeq: _*))(EnrichedStatus[F]) } }
Example 20
Source File: Listable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.util.CirceEntityCodec._ import com.goyeau.kubernetes.client.util.Uris.addLabels import io.circe._ import org.http4s._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.http4s.Method._ private[client] trait Listable[F[_], Resource] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri implicit protected def listDecoder: Decoder[Resource] @deprecated("Use list() instead", "0.4.0") def list: F[Resource] = list() def list(labels: Map[String, String] = Map.empty): F[Resource] = { val uri = addLabels(labels, config.server.resolve(resourceUri)) httpClient.expect[Resource](GET(uri, config.authorization.toSeq: _*)) } }
Example 21
Source File: Watchable.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.operation import cats.effect.Sync import cats.syntax.either._ import com.goyeau.kubernetes.client.util.Uris.addLabels import com.goyeau.kubernetes.client.{KubeConfig, WatchEvent} import fs2.Stream import io.circe.jawn.CirceSupportParser import io.circe.{Decoder, Json} import jawnfs2._ import org.http4s.Method._ import org.http4s._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.typelevel.jawn.Facade private[client] trait Watchable[F[_], Resource] extends Http4sClientDsl[F] { protected def httpClient: Client[F] implicit protected val F: Sync[F] protected def config: KubeConfig protected def resourceUri: Uri protected def watchResourceUri: Uri = resourceUri implicit protected def resourceDecoder: Decoder[Resource] implicit val parserFacade: Facade[Json] = new CirceSupportParser(None, false).facade def watch(labels: Map[String, String] = Map.empty): Stream[F, Either[String, WatchEvent[Resource]]] = { val uri = addLabels(labels, config.server.resolve(watchResourceUri)) val req = GET(uri.+?("watch", "1"), config.authorization.toSeq: _*) jsonStream(req).map(_.as[WatchEvent[Resource]].leftMap(_.getMessage)) } private def jsonStream(req: F[Request[F]]): Stream[F, Json] = for { request <- Stream.eval(req) json <- httpClient.stream(request).flatMap(_.body.chunks.parseJsonStream) } yield json }
Example 22
Source File: Content.scala From github with MIT License | 5 votes |
package io.chrisdavenport.github.endpoints.repositories import cats.implicits._ import cats.data._ import cats.effect._ import io.chrisdavenport.github.data.Content._ import org.http4s._ import org.http4s.implicits._ import org.http4s.client.Client import io.chrisdavenport.github.Auth import io.chrisdavenport.github.internals.GithubMedia._ import io.chrisdavenport.github.internals.RequestConstructor object Content { def contentsFor[F[_]: Sync]( owner: String, repo: String, path: String, ref: Option[String], auth: Option[Auth] ): Kleisli[F, Client[F], Content] = RequestConstructor.runRequestWithNoBody[F, Content]( auth, Method.GET, (uri"repos" / owner / repo / "contents" / path) .withOptionQueryParam("ref", ref) ) def readmeFor[F[_]: Sync]( owner: String, repo: String, auth: Option[Auth] ) = RequestConstructor.runRequestWithNoBody[F, Content]( auth, Method.GET, uri"repos" / owner / repo / "readme" ) def createFile[F[_]: Sync]( owner: String, repo: String, createFile: CreateFile, auth: Auth ) = RequestConstructor.runRequestWithBody[F, CreateFile, ContentResult]( auth.some, Method.PUT, uri"repos" / owner / repo / "contents" / createFile.path, createFile ) def updateFile[F[_]: Sync]( owner: String, repo: String, updateFile: UpdateFile, auth: Auth ) = RequestConstructor.runRequestWithBody[F, UpdateFile, ContentResult]( auth.some, Method.PUT, uri"repos" / owner / repo / "contents" / updateFile.path, updateFile ) def deleteFile[F[_]: Sync]( owner: String, repo: String, deleteFile: DeleteFile, auth: Auth ) = RequestConstructor.runRequestWithBody[F, DeleteFile, Unit]( auth.some, Method.DELETE, uri"repos" / owner / repo / "contents" / deleteFile.path, deleteFile ) }
Example 23
package org.aws4s.s3 import cats.effect.Effect import org.aws4s._ import org.http4s.client.Client import fs2.Stream import org.aws4s.core.ExtraEntityDecoderInstances._ import org.aws4s.core.Service case class S3[F[_]: Effect](client: F[Client[F]], region: Region, credentials: () => Credentials) extends Service[F, Nothing] { val listBuckets: F[ListBucketsSuccess] = run { ListBuckets(region) } def putObject( bucket: BucketName, objectPath: ObjectPath, obj: F[Stream[F, Byte]], payloadSigning: PayloadSigning = PayloadSigning.Unsigned, ): F[Unit] = run { PutObject(region, bucket, objectPath, obj, payloadSigning) } def deleteObject( bucket: BucketName, objectPath: ObjectPath ): F[Unit] = run { DeleteObject(region, bucket, objectPath) } def getObject( bucket: BucketName, objectPath: ObjectPath ): F[Stream[F, Byte]] = run { GetObject(region, bucket, objectPath) } }
Example 24
Source File: DynamoDb.scala From aws4s with MIT License | 5 votes |
package org.aws4s.dynamodb import cats.data.NonEmptyList import cats.effect.Effect import io.circe.Json import org.aws4s.core.Service import org.aws4s.{Credentials, Region} import org.http4s.client.Client import org.aws4s.core.ExtraEntityDecoderInstances._ case class DynamoDb[F[_]: Effect](client: F[Client[F]], region: Region, credentials: () => Credentials) extends Service[F, Json] { def createTable(tableName: TableName, indices: NonEmptyList[Index], provisionedThroughput: ProvisionedThroughput): F[CreateTableSuccess] = run { CreateTable(region, indices, tableName, provisionedThroughput) } def deleteTable(tableName: TableName): F[DeleteTableSuccess] = run { DeleteTable(region, tableName) } }
Example 25
package org.aws4s.sqs import cats.effect.Effect import org.aws4s.core.Service import org.aws4s.Credentials import org.http4s.client.Client case class Sqs[F[_]: Effect](client: F[Client[F]], credentials: () => Credentials) extends Service[F, String] { def sendMessage( q: Queue, messageBody: MessageBody, delaySeconds: Option[DelaySeconds] = None, messageDeduplicationId: Option[MessageDeduplicationId] = None ): F[SendMessageSuccess] = run { SendMessage( q, messageBody, delaySeconds, messageDeduplicationId ) } def receiveMessage( q: Queue, maxNumberOfMessages: Option[MaxNumberOfMessages] = None, visibilityTimeout: Option[VisibilityTimeout] = None, waitTimeSeconds: Option[WaitTimeSeconds] = None, receiveRequestAttemptId: Option[ReceiveRequestAttemptId] = None, ): F[ReceiveMessageSuccess] = run { ReceiveMessage( q, maxNumberOfMessages, visibilityTimeout, waitTimeSeconds, receiveRequestAttemptId ) } def deleteMessage( q: Queue, receiptHandle: ReceiptHandle, ): F[Unit] = run { DeleteMessage( q, receiptHandle ) } }
Example 26
package org.aws4s.kms import cats.effect.Effect import io.circe.Json import org.aws4s.core.ExtraEntityDecoderInstances._ import org.aws4s.core.Service import org.aws4s.{Credentials, Region} import org.http4s.client.Client case class Kms[F[_]: Effect](client: F[Client[F]], region: Region, credentials: () => Credentials) extends Service[F, Json] { def encrypt( keyId: KeyId, plaintext: Plaintext, context: Option[EncryptionContext] = None, grantTokens: Option[GrantTokens] = None, ): F[EncryptSuccess] = run { Encrypt( region, keyId, plaintext, context, grantTokens ) } def decrypt( ciphertext: Ciphertext, context: Option[EncryptionContext] = None, grantTokens: Option[GrantTokens] = None, ): F[DecryptSuccess] = run { Decrypt(region, ciphertext, context, grantTokens) } def createKey(description: Option[KeyDescription] = None): F[CreateKeySuccess] = run { CreateKey(region, description) } def scheduleKeyDeletion(keyId: KeyId, pendingWindowInDays: Option[PendingWindowInDays] = None): F[ScheduleKeyDeletionSuccess] = run { ScheduleKeyDeletion(region, keyId, pendingWindowInDays) } }
Example 27
Source File: Http4sBlazeClientModule.scala From scala-server-toolkit with MIT License | 5 votes |
package com.avast.sst.http4s.client import cats.effect.{ConcurrentEffect, Resource} import javax.net.ssl.SSLContext import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import scala.concurrent.ExecutionContext object Http4sBlazeClientModule { def make[F[_]: ConcurrentEffect]( config: Http4sBlazeClientConfig, executionContext: ExecutionContext, sslContext: Option[SSLContext] = None ): Resource[F, Client[F]] = { val builder = BlazeClientBuilder[F](executionContext) .withResponseHeaderTimeout(config.responseHeaderTimeout) .withIdleTimeout(config.idleTimeout) .withRequestTimeout(config.requestTimeout) .withConnectTimeout(config.connectTimeout) .withUserAgent(config.userAgent) .withMaxTotalConnections(config.maxTotalConnections) .withMaxWaitQueueLimit(config.maxWaitQueueLimit) .withMaxConnectionsPerRequestKey(Function.const(config.maxConnectionsPerRequestkey)) .withCheckEndpointAuthentication(config.checkEndpointIdentification) .withMaxResponseLineSize(config.maxResponseLineSize) .withMaxHeaderLength(config.maxHeaderLength) .withMaxChunkSize(config.maxChunkSize) .withChunkBufferMaxSize(config.chunkBufferMaxSize) .withParserMode(config.parserMode) .withBufferSize(config.bufferSize) sslContext.map(builder.withSslContext).getOrElse(builder).resource } }
Example 28
Source File: Http4sClientCircuitBreakerModule.scala From scala-server-toolkit with MIT License | 5 votes |
package com.avast.sst.http4s.client.monix.catnap import cats.effect.{Resource, Sync} import cats.syntax.applicativeError._ import cats.syntax.flatMap._ import monix.catnap.CircuitBreaker import org.http4s.Response import org.http4s.client.Client object Http4sClientCircuitBreakerModule { def make[F[_]: Sync]( client: Client[F], circuitBreaker: CircuitBreaker[F], httpStatusClassifier: HttpStatusClassifier = HttpStatusClassifier.default ): Client[F] = { val F = Sync[F] class ServerFailure(val response: Response[F], val close: F[Unit]) extends Exception Client[F] { request => val raisedInternal = client.run(request).allocated.flatMap { case tuple @ (response, _) if !httpStatusClassifier.isServerFailure(response.status) => F.pure(tuple) case (response, close) => F.raiseError[(Response[F], F[Unit])](new ServerFailure(response, close)) } val lifted = circuitBreaker.protect(raisedInternal).recover { case serverFailure: ServerFailure => (serverFailure.response, serverFailure.close) } Resource(lifted) } } }
Example 29
Source File: Http4sRoutingModule.scala From scala-server-toolkit with MIT License | 5 votes |
package com.avast.sst.example.module import cats.implicits._ import com.avast.sst.example.service.RandomService import com.avast.sst.http4s.server.Http4sRouting import com.avast.sst.http4s.server.micrometer.MicrometerHttp4sServerMetricsModule import org.http4s.client.Client import org.http4s.dsl.Http4sDsl import org.http4s.{HttpApp, HttpRoutes} import zio.Task import zio.interop.catz._ class Http4sRoutingModule( randomService: RandomService, client: Client[Task], serverMetricsModule: MicrometerHttp4sServerMetricsModule[Task] ) extends Http4sDsl[Task] { import serverMetricsModule._ private val helloWorldRoute = routeMetrics.wrap("hello")(Ok("Hello World!")) private val routes = HttpRoutes.of[Task] { case GET -> Root / "hello" => helloWorldRoute case GET -> Root / "random" => randomService.randomNumber.map(_.show).flatMap(Ok(_)) case GET -> Root / "circuit-breaker" => client.expect[String]("https://httpbin.org/status/500").flatMap(Ok(_)) } val router: HttpApp[Task] = Http4sRouting.make { serverMetrics { routes } } }
Example 30
Source File: Users.scala From github with MIT License | 5 votes |
package io.chrisdavenport.github.endpoints import cats.implicits._ import cats.data._ import cats.effect._ import io.chrisdavenport.github.data.Users._ import org.http4s._ import org.http4s.implicits._ import org.http4s.client.Client import fs2.Stream import io.chrisdavenport.github.Auth import io.chrisdavenport.github.internals.GithubMedia._ import io.chrisdavenport.github.internals.RequestConstructor object Users { def userInfoFor[F[_]: Sync](username: String, auth: Option[Auth]): Kleisli[F, Client[F], User] = RequestConstructor.runRequestWithNoBody[F, User]( auth, Method.GET, uri"users" / username ) def ownerInfoFor[F[_]: Sync](owner: String, auth: Option[Auth]): Kleisli[F, Client[F], Owner] = RequestConstructor.runRequestWithNoBody[F, Owner]( auth, Method.GET, uri"users" / owner ) def userInfoAuthenticatedUser[F[_]: Sync](auth: Auth): Kleisli[F, Client[F], User] = RequestConstructor.runRequestWithNoBody[F, User]( auth.some, Method.GET, uri"user" ) // We expose this as the returned list for each request // that way users can monitor how many requests they make // and can know where they stand in regards to their cap. def getAllUsers[F[_]: Sync]( since: Option[String], auth: Option[Auth] ): Kleisli[Stream[F, ?], Client[F], List[SimpleOwner]] = RequestConstructor.runPaginatedRequest[F, List[SimpleOwner]]( auth, uri"users".withOptionQueryParam("since", since) ) // Patch so presently only updates. Unsure // if null values are removed entirely, so // for the first draft dropNull values // possibly in the future rework def updateAuthenticatedUser[F[_]: Sync]( auth: Auth, name: Option[String], email: Option[String], blog: Option[String], company: Option[String], location: Option[String], hireable: Option[Boolean], bio: Option[String] ): Kleisli[F, Client[F], User] = { import io.circe._ def fromOptionJson[A](fa: Option[A])(f: A => Json): Json = fa.fold(Json.Null)(f) def fromOptionString(fa: Option[String]): Json = fromOptionJson(fa)(Json.fromString) val json = Json.obj( "name" -> fromOptionString(name), "email" -> fromOptionString(email), "blog" -> fromOptionString(blog), "company" -> fromOptionString(company), "location" -> fromOptionString(location), "hireable" -> fromOptionJson(hireable)(Json.fromBoolean), "bio" -> fromOptionString(bio) ).dropNullValues RequestConstructor.runRequestWithBody[F, Json, User]( auth.some, Method.PATCH, uri"user", json ) } }
Example 31
Source File: Search.scala From github with MIT License | 5 votes |
package io.chrisdavenport.github.endpoints import cats.data._ import cats.effect._ import fs2.Stream import io.chrisdavenport.github.data.Repositories._ import org.http4s.implicits._ import org.http4s.client.Client import io.chrisdavenport.github.Auth import io.chrisdavenport.github.data.{Order, SearchResult, Sort} import io.chrisdavenport.github.data.Users.User import io.chrisdavenport.github.internals.GithubMedia._ import io.chrisdavenport.github.internals.RequestConstructor object Search { def users[F[_]: Sync]( q: String, sort: Option[Sort.User], order: Option[Order], auth: Option[Auth] ): Kleisli[Stream[F, *], Client[F], SearchResult[User]] = RequestConstructor.runPaginatedRequest[F, SearchResult[User]]( auth, (uri"search" / "users") .withQueryParam("q", q) .withOptionQueryParam("sort", sort.flatMap(Sort.toOptionalParam)) .withOptionQueryParam("order", order.flatMap(Order.toOptionalParam)) ) }
Example 32
Source File: Http4sFullTracerTest.scala From guardrail with MIT License | 5 votes |
package core.Http4s import _root_.tracer.client.{ http4s => cdefs } import _root_.tracer.server.http4s.addresses.{ AddressesHandler, AddressesResource, GetAddressResponse, GetAddressesResponse } import _root_.tracer.server.http4s.users.{ GetUserResponse, UsersHandler, UsersResource } import _root_.tracer.server.{ http4s => sdefs } import _root_.tracer.client.http4s.users.UsersClient import _root_.tracer.client.http4s.addresses.AddressesClient import _root_.tracer.server.http4s.Http4sImplicits.TraceBuilder import cats.effect.IO import org.http4s.{ Header, HttpRoutes, Request } import org.http4s.client.Client import org.http4s.implicits._ import org.http4s.syntax.StringSyntax import org.scalatest.{ EitherValues, FunSuite, Matchers } class Http4sFullTracerTest extends FunSuite with Matchers with EitherValues with StringSyntax { val traceHeaderKey = "tracer-label" def log(line: String): Unit = () def trace: String => Request[IO] => TraceBuilder[IO] = { name => request => // In a real environment, this would be where you could establish a new // tracing context and inject that fresh header value. log(s"Expecting all requests to have ${traceHeaderKey} header.") traceBuilder(request.headers.get(traceHeaderKey.ci).get.value) } def traceBuilder(parentValue: String): TraceBuilder[IO] = { name => httpClient => Client { req => httpClient.run(req.putHeaders(Header(traceHeaderKey, parentValue))) } } test("full tracer: passing headers through multiple levels") { // Establish the "Address" server val server2: HttpRoutes[IO] = new AddressesResource(trace).routes( new AddressesHandler[IO] { def getAddress(respond: GetAddressResponse.type)(id: String)(traceBuilder: TraceBuilder[IO]) = IO.pure(if (id == "addressId") { respond.Ok(sdefs.definitions.Address(Some("line1"), Some("line2"), Some("line3"))) } else sdefs.addresses.GetAddressResponse.NotFound) def getAddresses(respond: GetAddressesResponse.type)()(traceBuilder: TraceBuilder[IO]) = IO.pure(sdefs.addresses.GetAddressesResponse.NotFound) } ) // Establish the "User" server val server1: HttpRoutes[IO] = new UsersResource(trace).routes( new UsersHandler[IO] { // ... using the "Address" server explicitly in the addressesClient val addressesClient = AddressesClient.httpClient(Client.fromHttpApp(server2.orNotFound)) def getUser(respond: GetUserResponse.type)(id: String)(traceBuilder: TraceBuilder[IO]) = addressesClient .getAddress(traceBuilder, "addressId") .map { case cdefs.addresses.GetAddressResponse.Ok(address) => respond.Ok(sdefs.definitions.User("1234", sdefs.definitions.UserAddress(address.line1, address.line2, address.line3))) case cdefs.addresses.GetAddressResponse.NotFound => respond.NotFound } } ) // Build a UsersClient using the User server val usersClient = UsersClient.httpClient(Client.fromHttpApp(server1.orNotFound)) // As this is the entry point, we either have a tracing header from // somewhere else, or we generate one for top-level request. val testTrace = traceBuilder("top-level-request") // Make a request against the mock servers using a hard-coded user ID val retrieved: cdefs.users.GetUserResponse = usersClient.getUser(testTrace, "1234").attempt.unsafeRunSync().right.value retrieved shouldBe cdefs.users.GetUserResponse .Ok(cdefs.definitions.User("1234", cdefs.definitions.UserAddress(Some("line1"), Some("line2"), Some("line3")))) } }
Example 33
Source File: Forks.scala From github with MIT License | 5 votes |
package io.chrisdavenport.github.endpoints.repositories import cats.implicits._ import cats.data._ import cats.effect._ import fs2.Stream import io.chrisdavenport.github.Auth import io.chrisdavenport.github.data.Repositories.Repo import io.chrisdavenport.github.data.Sort import io.chrisdavenport.github.internals.GithubMedia._ import io.chrisdavenport.github.internals.RequestConstructor import org.http4s._ import org.http4s.implicits._ import org.http4s.client.Client object Forks { def list[F[_]: Sync]( owner: String, repo: String, sort: Option[Sort.Fork], auth: Auth ): Kleisli[Stream[F, *], Client[F], List[Repo]] = RequestConstructor.runPaginatedRequest[F, List[Repo]]( auth.some, (uri"repos" / owner / repo / "forks") .withOptionQueryParam("sort", sort.flatMap(Sort.toOptionalParam)) ) }
Example 34
Source File: Repositories.scala From github with MIT License | 5 votes |
package io.chrisdavenport.github.endpoints import cats.implicits._ import cats.data._ import cats.effect._ import io.chrisdavenport.github.data.Repositories._ import org.http4s._ import org.http4s.implicits._ import org.http4s.client.Client import io.chrisdavenport.github.Auth import io.chrisdavenport.github.internals.RequestConstructor object Repositories { def repository[F[_]: Sync]( owner: String, repo: String, auth: Option[Auth] ): Kleisli[F, Client[F], Repo] = { import io.chrisdavenport.github.internals.GithubMedia._ RequestConstructor.runRequestWithNoBody[F, Repo]( auth, Method.GET, uri"repos" / owner / repo ) } def createRepo[F[_]: Sync]( newRepo: NewRepo, auth: Auth ): Kleisli[F, Client[F], Repo] = { import io.chrisdavenport.github.internals.GithubMedia._ RequestConstructor.runRequestWithBody[F, NewRepo, Repo]( auth.some, Method.POST, uri"user/repos", newRepo ) } def createOrganizationRepo[F[_]: Sync]( org: String, newRepo: NewRepo, auth: Auth ): Kleisli[F, Client[F], Repo] = { import io.chrisdavenport.github.internals.GithubMedia._ RequestConstructor.runRequestWithBody[F, NewRepo, Repo]( auth.some, Method.POST, uri"orgs" / org / "repos", newRepo ) } def edit[F[_]: Sync]( owner: String, repo: String, editRepo: EditRepo, auth: Auth ): Kleisli[F, Client[F], Repo] = { import io.chrisdavenport.github.internals.GithubMedia._ RequestConstructor.runRequestWithBody[F, EditRepo, Repo]( auth.some, Method.PATCH, uri"repos" / owner / repo, editRepo ) } def delete[F[_]: Sync]( owner: String, repo: String, auth: Auth ): Kleisli[F, Client[F], Unit] = RequestConstructor.runRequestWithNoBody[F, Unit]( auth.some, Method.DELETE, uri"repos" / owner / repo ) }
Example 35
Source File: AdserverHttpClientBuilder.scala From scala-openrtb with Apache License 2.0 | 5 votes |
package com.powerspace.openrtb.examples.rtb.http4s.adserver import com.google.openrtb.{BidRequest, BidResponse} import com.powerspace.openrtb.examples.rtb.http4s.common.ExampleSerdeModule import com.powerspace.openrtb.json.SerdeModule import io.circe.{Decoder, Encoder} import monix.eval.Task import org.http4s.Uri.{Authority, RegName, Scheme} import org.http4s.client.Client import org.http4s.{EntityDecoder, EntityEncoder, Method, Request, Uri} object AdserverHttpClientBuilder { import org.http4s.circe._ val serdeModule: SerdeModule = ExampleSerdeModule implicit val bidRequestEncoder: Encoder[BidRequest] = serdeModule.bidRequestEncoder implicit val bidRequestEntityEncoder: EntityEncoder[Task, BidRequest] = jsonEncoderOf[Task, BidRequest] implicit val bidResponseDecoder: Decoder[BidResponse] = serdeModule.bidResponseDecoder implicit val bidResponseEntityDecoder: EntityDecoder[Task, BidResponse] = jsonOf[Task, BidResponse] def bid(client: Client[Task], bidRequest: BidRequest): Task[Option[BidResponse]] = { val url = Uri( scheme = Some(Scheme.http), authority = Some(Authority(host = RegName("localhost"), port = Some(9000))), path = "/bid" ) val httpRequest = Request[Task]( method = Method.POST, uri = url ).withEntity[BidRequest](bidRequest) client.expectOption[BidResponse](httpRequest) } }
Example 36
Source File: AdserverApp.scala From scala-openrtb with Apache License 2.0 | 5 votes |
package com.powerspace.openrtb.examples.rtb.http4s.adserver import cats.effect.Resource import com.google.openrtb.{BidRequest, BidResponse} import com.powerspace.openrtb.examples.rtb.http4s.common.ExampleSerdeModule import io.circe.{Encoder, Json} import monix.eval.Task import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import scala.concurrent.duration.Duration object AdserverApp extends App { import monix.execution.Scheduler.Implicits.global val httpClient: Resource[Task, Client[Task]] = buildHttpClient() val potentialBidResponse = httpBid(httpClient) private val bidRequest = Adserver.buildBidRequest() potentialBidResponse .map(bidResponse => { bidResponse.foreach(br => println(buildAuctionString(br))) }) .runSyncUnsafe(Duration.Inf) private def buildHttpClient(): Resource[Task, Client[Task]] = { BlazeClientBuilder[Task](global).resource } private def httpBid(httpClient: Resource[Task, Client[Task]]) = httpClient.use(AdserverHttpClientBuilder.bid(_, bidRequest)) private def buildAuctionString(bidResponse: BidResponse) = { case class Auction(bidRequest: BidRequest, bidResponse: BidResponse) val auctionEncoder = new Encoder[Auction] { override def apply(auction: Auction): Json = Json.obj( ("request", ExampleSerdeModule.bidRequestEncoder.apply(auction.bidRequest)), ("response", ExampleSerdeModule.bidResponseEncoder.apply(auction.bidResponse)) ) } auctionEncoder(Auction(bidRequest, bidResponse)).toString() } }
Example 37
Source File: resources.scala From pfps-shopping-cart with Apache License 2.0 | 5 votes |
package shop import cats.effect._ import cats.implicits._ import config.data._ import dev.profunktor.redis4cats.{ Redis, RedisCommands } import dev.profunktor.redis4cats.log4cats._ import eu.timepit.refined.auto._ import io.chrisdavenport.log4cats.Logger import natchez.Trace.Implicits.noop // needed for skunk import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import scala.concurrent.ExecutionContext import skunk._ final case class AppResources[F[_]]( client: Client[F], psql: Resource[F, Session[F]], redis: RedisCommands[F, String, String] ) object AppResources { def make[F[_]: ConcurrentEffect: ContextShift: Logger]( cfg: AppConfig ): Resource[F, AppResources[F]] = { def mkPostgreSqlResource(c: PostgreSQLConfig): SessionPool[F] = Session .pooled[F]( host = c.host.value, port = c.port.value, user = c.user.value, database = c.database.value, max = c.max.value ) def mkRedisResource(c: RedisConfig): Resource[F, RedisCommands[F, String, String]] = Redis[F].utf8(c.uri.value) def mkHttpClient(c: HttpClientConfig): Resource[F, Client[F]] = BlazeClientBuilder[F](ExecutionContext.global) .withConnectTimeout(c.connectTimeout) .withRequestTimeout(c.requestTimeout) .resource ( mkHttpClient(cfg.httpClientConfig), mkPostgreSqlResource(cfg.postgreSQL), mkRedisResource(cfg.redis) ).mapN(AppResources.apply[F]) } }
Example 38
Source File: HttpClients.scala From pfps-shopping-cart with Apache License 2.0 | 5 votes |
package shop.modules import cats.effect._ import org.http4s.client.Client import shop.config.data.PaymentConfig import shop.http.clients._ object HttpClients { def make[F[_]: Sync]( cfg: PaymentConfig, client: Client[F] ): F[HttpClients[F]] = Sync[F].delay( new HttpClients[F] { def payment: PaymentClient[F] = new LivePaymentClient[F](cfg, client) } ) } trait HttpClients[F[_]] { def payment: PaymentClient[F] }
Example 39
Source File: ExchangeRateService.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import java.net.ConnectException import cats.MonadError import cats.effect.Effect import cats.syntax.all._ import com.smartbackpackerapp.common.Log import com.smartbackpackerapp.config.SBConfiguration import com.smartbackpackerapp.model.Currency import io.circe.generic.auto._ import org.http4s.circe._ import org.http4s.client.{Client, UnexpectedStatus} class ExchangeRateService[F[_] : Effect](client: Client[F], sbConfig: SBConfiguration[F]) (implicit L: Log[F]) extends AbstractExchangeRateService[F](sbConfig) { override protected def retrieveExchangeRate(uri: String): F[CurrencyExchangeDTO] = { client.expect[CurrencyExchangeDTO](uri)(jsonOf[F, CurrencyExchangeDTO]) } } abstract class AbstractExchangeRateService[F[_]](sbConfig: SBConfiguration[F]) (implicit F: MonadError[F, Throwable], L: Log[F]) { protected val fixerUri: Currency => Currency => F[String] = baseCurrency => foreignCurrency => { val uri = sbConfig.fixerBaseUri.map(_.getOrElse("http://localhost:8081")) uri.map(x => s"$x/latest?base=${baseCurrency.value}&symbols=${foreignCurrency.value}") } protected def retrieveExchangeRate(uri: String): F[CurrencyExchangeDTO] // We don't want the whole destination service to fail if the exchange rate service is unavailable // so the `UnexpectedStatus` and `ConnectException` errors are treated as an empty exchange rate def exchangeRateFor(baseCurrency: Currency, foreignCurrency: Currency): F[CurrencyExchangeDTO] = { val ifEmpty = CurrencyExchangeDTO.empty(baseCurrency).pure[F] def performRequest(uri: String): F[CurrencyExchangeDTO] = retrieveExchangeRate(uri).recoverWith { case e: ConnectException => L.error(e).flatMap(_ => ifEmpty) case _: UnexpectedStatus => ifEmpty } validateCurrencies(baseCurrency, foreignCurrency).fold(ifEmpty) { _ => for { uri <- fixerUri(baseCurrency)(foreignCurrency) _ <- L.info(s"Retrieving currency exchange from: $uri") er <- performRequest(uri) } yield { if (er.rates.nonEmpty) er else er.copy(rates = Map(baseCurrency.value -> -1.0)) } } } private def validateCurrencies(baseCurrency: Currency, foreignCurrency: Currency): Option[Currency] = { if (baseCurrency == foreignCurrency) none[Currency] else foreignCurrency.some } }
Example 40
Source File: CustomResourcesApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.crd.{CrdContext, CustomResource, CustomResourceList} import com.goyeau.kubernetes.client.operation._ import com.goyeau.kubernetes.client.util.CirceEntityCodec._ import com.goyeau.kubernetes.client.util.EnrichedStatus import io.circe._ import org.http4s.Method._ import org.http4s.client.Client import org.http4s.implicits._ import org.http4s.{Status, Uri} private[client] case class CustomResourcesApi[F[_], A, B]( httpClient: Client[F], config: KubeConfig, context: CrdContext )(implicit val F: Sync[F], val listDecoder: Decoder[CustomResourceList[A, B]], encoder: Encoder[CustomResource[A, B]], decoder: Decoder[CustomResource[A, B]] ) extends Listable[F, CustomResourceList[A, B]] { val resourceUri: Uri = uri"/apis" / context.group / context.version / context.plural def namespace(namespace: String): NamespacedCustomResourcesApi[F, A, B] = NamespacedCustomResourcesApi(httpClient, config, context, namespace) } private[client] case class NamespacedCustomResourcesApi[F[_], A, B]( httpClient: Client[F], config: KubeConfig, context: CrdContext, namespace: String )(implicit val F: Sync[F], val resourceEncoder: Encoder[CustomResource[A, B]], val resourceDecoder: Decoder[CustomResource[A, B]], val listDecoder: Decoder[CustomResourceList[A, B]] ) extends Creatable[F, CustomResource[A, B]] with Replaceable[F, CustomResource[A, B]] with Gettable[F, CustomResource[A, B]] with Listable[F, CustomResourceList[A, B]] with Deletable[F] with GroupDeletable[F] with Watchable[F, CustomResource[A, B]] { val resourceUri: Uri = uri"/apis" / context.group / context.version / "namespaces" / namespace / context.plural def updateStatus(name: String, resource: CustomResource[A, B]): F[Status] = httpClient.fetch( PUT(resource, config.server.resolve(resourceUri / name / "status"), config.authorization.toSeq: _*) )( EnrichedStatus[F] ) }
Example 41
Source File: CronJobsApi.scala From kubernetes-client with Apache License 2.0 | 5 votes |
package com.goyeau.kubernetes.client.api import cats.effect.Sync import com.goyeau.kubernetes.client.KubeConfig import com.goyeau.kubernetes.client.operation._ import io.circe._ import io.k8s.api.batch.v1beta1.{CronJob, CronJobList} import org.http4s.Uri import org.http4s.client.Client import org.http4s.implicits._ private[client] case class CronJobsApi[F[_]](httpClient: Client[F], config: KubeConfig)(implicit val F: Sync[F], val listDecoder: Decoder[CronJobList], encoder: Encoder[CronJob], decoder: Decoder[CronJob] ) extends Listable[F, CronJobList] { val resourceUri: Uri = uri"/apis" / "batch" / "v1beta1" / "cronjobs" def namespace(namespace: String): NamespacedCronJobsApi[F] = NamespacedCronJobsApi(httpClient, config, namespace) } private[client] case class NamespacedCronJobsApi[F[_]](httpClient: Client[F], config: KubeConfig, namespace: String)( implicit val F: Sync[F], val resourceEncoder: Encoder[CronJob], val resourceDecoder: Decoder[CronJob], val listDecoder: Decoder[CronJobList] ) extends Creatable[F, CronJob] with Replaceable[F, CronJob] with Gettable[F, CronJob] with Listable[F, CronJobList] with Deletable[F] with DeletableTerminated[F] with GroupDeletable[F] with Watchable[F, CronJob] { val resourceUri: Uri = uri"/apis" / "batch" / "v1beta1" / "namespaces" / namespace / "cronjobs" }
Example 42
Source File: HttpMetricsSpec.scala From kamon-http4s with Apache License 2.0 | 5 votes |
package kamon.http4s import cats.effect._ import kamon.testkit.InstrumentInspection import org.http4s.HttpRoutes import org.http4s.dsl.io._ import org.http4s.server.Server import org.http4s.server.blaze.BlazeServerBuilder import org.scalatest.concurrent.Eventually import org.scalatest.time.SpanSugar import org.scalatest.{Matchers, OptionValues, WordSpec} import cats.implicits._ import kamon.http4s.middleware.server.KamonSupport import kamon.instrumentation.http.HttpServerMetrics import org.http4s.client.blaze.BlazeClientBuilder import org.http4s.client.Client import scala.concurrent.ExecutionContext import org.http4s.implicits._ class HttpMetricsSpec extends WordSpec with Matchers with Eventually with SpanSugar with InstrumentInspection.Syntax with OptionValues { implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global) implicit val timer: Timer[IO] = IO.timer(ExecutionContext.global) val srv = BlazeServerBuilder[IO] .bindLocal(43567) .withHttpApp(KamonSupport(HttpRoutes.of[IO] { case GET -> Root / "tracing" / "ok" => Ok("ok") case GET -> Root / "tracing" / "not-found" => NotFound("not-found") case GET -> Root / "tracing" / "error" => InternalServerError("This page will generate an error!") }, "/127.0.0.1", 43567).orNotFound) .resource val client = BlazeClientBuilder[IO](ExecutionContext.global).withMaxTotalConnections(10).resource val metrics = Resource.liftF(IO(HttpServerMetrics.of("http4s.server", "/127.0.0.1", 43567))) def withServerAndClient[A](f: (Server[IO], Client[IO], HttpServerMetrics.HttpServerInstruments) => IO[A]): A = (srv, client, metrics).tupled.use(f.tupled).unsafeRunSync() private def get[F[_]: ConcurrentEffect](path: String)(server: Server[F], client: Client[F]): F[String] = { client.expect[String](s"http://127.0.0.1:${server.address.getPort}$path") } "The HttpMetrics" should { "track the total of active requests" in withServerAndClient { (server, client, serverMetrics) => val requests = List .fill(100) { get("/tracing/ok")(server, client) }.parSequence_ val test = IO { serverMetrics.activeRequests.distribution().max should be > 1L serverMetrics.activeRequests.distribution().min shouldBe 0L } requests *> test } "track the response time with status code 2xx" in withServerAndClient { (server, client, serverMetrics) => val requests: IO[Unit] = List.fill(100)(get("/tracing/ok")(server, client)).sequence_ val test = IO(serverMetrics.requestsSuccessful.value should be >= 0L) requests *> test } "track the response time with status code 4xx" in withServerAndClient { (server, client, serverMetrics) => val requests: IO[Unit] = List.fill(100)(get("/tracing/not-found")(server, client).attempt).sequence_ val test = IO(serverMetrics.requestsClientError.value should be >= 0L) requests *> test } "track the response time with status code 5xx" in withServerAndClient { (server, client, serverMetrics) => val requests: IO[Unit] = List.fill(100)(get("/tracing/error")(server, client).attempt).sequence_ val test = IO(serverMetrics.requestsServerError.value should be >= 0L) requests *> test } } }
Example 43
Source File: SolrFtsClient.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.ftssolr import cats.effect._ import cats.implicits._ import fs2.Stream import docspell.common._ import docspell.ftsclient._ import org.http4s.client.Client import org.http4s.client.middleware.Logger import org.log4s.getLogger final class SolrFtsClient[F[_]: Effect]( solrUpdate: SolrUpdate[F], solrSetup: SolrSetup[F], solrQuery: SolrQuery[F] ) extends FtsClient[F] { def initialize: F[Unit] = solrSetup.setupSchema def search(q: FtsQuery): F[FtsResult] = solrQuery.query(q) def indexData(logger: Logger[F], data: Stream[F, TextData]): F[Unit] = modifyIndex(logger, data)(solrUpdate.add) def updateIndex(logger: Logger[F], data: Stream[F, TextData]): F[Unit] = modifyIndex(logger, data)(solrUpdate.update) def modifyIndex(logger: Logger[F], data: Stream[F, TextData])( f: List[TextData] => F[Unit] ): F[Unit] = (for { _ <- Stream.eval(logger.debug("Updating SOLR index")) chunks <- data.chunks res <- Stream.eval(f(chunks.toList).attempt) _ <- res match { case Right(()) => Stream.emit(()) case Left(ex) => Stream.eval(logger.error(ex)("Error updating with chunk of data")) } } yield ()).compile.drain def removeItem(logger: Logger[F], itemId: Ident): F[Unit] = logger.debug(s"Remove item '${itemId.id}' from index") *> solrUpdate.delete(s"${Field.itemId.name}:${itemId.id}", None) def removeAttachment(logger: Logger[F], attachId: Ident): F[Unit] = logger.debug(s"Remove attachment '${attachId.id}' from index") *> solrUpdate.delete(s"${Field.attachmentId.name}:${attachId.id}", None) def clearAll(logger: Logger[F]): F[Unit] = logger.info("Deleting complete full-text index!") *> solrUpdate.delete("*:*", Option(0)) def clear(logger: Logger[F], collective: Ident): F[Unit] = logger.info(s"Deleting full-text index for collective ${collective.id}") *> solrUpdate.delete(s"${Field.collectiveId.name}:${collective.id}", Option(0)) } object SolrFtsClient { private[this] val logger = getLogger def apply[F[_]: ConcurrentEffect]( cfg: SolrConfig, httpClient: Client[F] ): Resource[F, FtsClient[F]] = { val client = loggingMiddleware(cfg, httpClient) Resource.pure[F, FtsClient[F]]( new SolrFtsClient( SolrUpdate(cfg, client), SolrSetup(cfg, client), SolrQuery(cfg, client) ) ) } private def loggingMiddleware[F[_]: Concurrent]( cfg: SolrConfig, client: Client[F] ): Client[F] = Logger( logHeaders = true, logBody = cfg.logVerbose, logAction = Some((msg: String) => Sync[F].delay(logger.trace(msg))) )(client) }
Example 44
Source File: SolrQuery.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.ftssolr import cats.effect._ import docspell.ftsclient._ import docspell.ftssolr.JsonCodec._ import _root_.io.circe.syntax._ import org.http4s._ import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl trait SolrQuery[F[_]] { def query(q: QueryData): F[FtsResult] def query(q: FtsQuery): F[FtsResult] } object SolrQuery { def apply[F[_]: ConcurrentEffect](cfg: SolrConfig, client: Client[F]): SolrQuery[F] = { val dsl = new Http4sClientDsl[F] {} import dsl._ new SolrQuery[F] { val url = Uri.unsafeFromString(cfg.url.asString) / "query" def query(q: QueryData): F[FtsResult] = { val req = Method.POST(q.asJson, url) client.expect[FtsResult](req) } def query(q: FtsQuery): F[FtsResult] = { val fq = QueryData( cfg, List( Field.content, Field.content_de, Field.content_en, Field.itemName, Field.itemNotes, Field.attachmentName ), List( Field.id, Field.itemId, Field.collectiveId, Field("score"), Field.attachmentId, Field.attachmentName, Field.discriminator ), q ) query(fq) } } } }
Example 45
Source File: VCSExtraAlgTest.scala From scala-steward with Apache License 2.0 | 5 votes |
package org.scalasteward.core.vcs import cats.effect.IO import org.http4s.HttpRoutes import org.http4s.client.Client import org.http4s.dsl.io._ import org.http4s.implicits._ import org.scalasteward.core.TestInstances.ioLogger import org.scalasteward.core.TestSyntax._ import org.scalasteward.core.data.{ReleaseRelatedUrl, Update} import org.scalasteward.core.mock.MockContext.config import org.scalasteward.core.util.{HttpExistenceClient, Nel} import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers class VCSExtraAlgTest extends AnyFunSuite with Matchers { val routes: HttpRoutes[IO] = HttpRoutes.of[IO] { case HEAD -> Root / "foo" / "bar" / "compare" / "v0.1.0...v0.2.0" => Ok("exist") case HEAD -> Root / "foo" / "buz" / "compare" / "v0.1.0...v0.2.0" => PermanentRedirect() case _ => NotFound() } implicit val client = Client.fromHttpApp[IO](routes.orNotFound) implicit val httpExistenceClient = HttpExistenceClient.create[IO].allocated.map(_._1).unsafeRunSync() val vcsExtraAlg = VCSExtraAlg.create[IO] val updateFoo = Update.Single("com.example" % "foo" % "0.1.0", Nel.of("0.2.0")) val updateBar = Update.Single("com.example" % "bar" % "0.1.0", Nel.of("0.2.0")) val updateBuz = Update.Single("com.example" % "buz" % "0.1.0", Nel.of("0.2.0")) test("getBranchCompareUrl") { vcsExtraAlg .getReleaseRelatedUrls(uri"https://github.com/foo/foo", updateFoo) .unsafeRunSync() shouldBe List.empty vcsExtraAlg .getReleaseRelatedUrls(uri"https://github.com/foo/bar", updateBar) .unsafeRunSync() shouldBe List( ReleaseRelatedUrl.VersionDiff(uri"https://github.com/foo/bar/compare/v0.1.0...v0.2.0") ) vcsExtraAlg .getReleaseRelatedUrls(uri"https://github.com/foo/buz", updateBuz) .unsafeRunSync() shouldBe List.empty } }
Example 46
Source File: HttpJsonClient.scala From scala-steward with Apache License 2.0 | 5 votes |
package org.scalasteward.core.util import cats.effect.Sync import cats.implicits._ import io.circe.{Decoder, Encoder} import org.http4s.Method.{GET, POST} import org.http4s.circe.{jsonEncoderOf, jsonOf} import org.http4s.client.Client import org.http4s._ import scala.util.control.NoStackTrace final class HttpJsonClient[F[_]: Sync](implicit client: Client[F] ) { type ModReq = Request[F] => F[Request[F]] def get[A: Decoder](uri: Uri, modify: ModReq): F[A] = request[A](GET, uri, modify) def post[A: Decoder](uri: Uri, modify: ModReq): F[A] = request[A](POST, uri, modify) def postWithBody[A: Decoder, B: Encoder](uri: Uri, body: B, modify: ModReq): F[A] = post[A](uri, modify.compose(_.withEntity(body)(jsonEncoderOf[F, B]))) private def request[A: Decoder](method: Method, uri: Uri, modify: ModReq): F[A] = client.expectOr[A](modify(Request[F](method, uri)))(resp => toUnexpectedResponse(uri, method, resp) )(jsonOf[F, A].transform(_.leftMap(failure => JsonParseError(uri, method, failure)))) private def toUnexpectedResponse( uri: Uri, method: Method, response: Response[F] ): F[Throwable] = { val body = response.body.through(fs2.text.utf8Decode).compile.string body.map(UnexpectedResponse(uri, method, response.headers, response.status, _)) } } final case class JsonParseError( uri: Uri, method: Method, underlying: DecodeFailure ) extends DecodeFailure { val message = s"uri: $uri\nmethod: $method\nmessage: ${underlying.message}" override def cause: Option[Throwable] = underlying.some override def toHttpResponse[F[_]](httpVersion: HttpVersion): Response[F] = underlying.toHttpResponse(httpVersion) } final case class UnexpectedResponse( uri: Uri, method: Method, headers: Headers, status: Status, body: String ) extends RuntimeException with NoStackTrace { override def getMessage: String = s"uri: $uri\nmethod: $method\nstatus: $status\nheaders: $headers\nbody: $body" }
Example 47
Source File: HttpExistenceClient.scala From scala-steward with Apache License 2.0 | 5 votes |
package org.scalasteward.core.util import cats.effect.{Async, Resource} import cats.implicits._ import com.github.benmanes.caffeine.cache.Caffeine import io.chrisdavenport.log4cats.Logger import org.http4s.client.Client import org.http4s.{Method, Request, Status, Uri} import org.scalasteward.core.application.Config import scalacache.CatsEffect.modes._ import scalacache.caffeine.CaffeineCache import scalacache.{Async => _, _} final class HttpExistenceClient[F[_]](statusCache: Cache[Status])(implicit client: Client[F], logger: Logger[F], mode: Mode[F], F: MonadThrowable[F] ) { def exists(uri: Uri): F[Boolean] = status(uri).map(_ === Status.Ok).handleErrorWith { throwable => logger.debug(throwable)(s"Failed to check if $uri exists").as(false) } private def status(uri: Uri): F[Status] = statusCache.cachingForMemoizeF(uri.renderString)(None) { client.status(Request[F](method = Method.HEAD, uri = uri)) } } object HttpExistenceClient { def create[F[_]](implicit config: Config, client: Client[F], logger: Logger[F], F: Async[F] ): Resource[F, HttpExistenceClient[F]] = { val buildCache = F.delay { CaffeineCache( Caffeine .newBuilder() .maximumSize(16384L) .expireAfterWrite(config.cacheTtl.length, config.cacheTtl.unit) .build[String, Entry[Status]]() ) } Resource.make(buildCache)(_.close().void).map(new HttpExistenceClient[F](_)) } }
Example 48
Source File: Context.scala From scala-steward with Apache License 2.0 | 5 votes |
package org.scalasteward.core.application import cats.Parallel import cats.effect._ import io.chrisdavenport.log4cats.Logger import io.chrisdavenport.log4cats.slf4j.Slf4jLogger import org.http4s.client.Client import org.http4s.client.asynchttpclient.AsyncHttpClient import org.scalasteward.core.buildtool.BuildToolDispatcher import org.scalasteward.core.buildtool.maven.MavenAlg import org.scalasteward.core.buildtool.mill.MillAlg import org.scalasteward.core.buildtool.sbt.SbtAlg import org.scalasteward.core.coursier.{CoursierAlg, VersionsCache} import org.scalasteward.core.edit.EditAlg import org.scalasteward.core.git.GitAlg import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg} import org.scalasteward.core.nurture.{NurtureAlg, PullRequestRepository} import org.scalasteward.core.persistence.JsonKeyValueStore import org.scalasteward.core.repocache.{RefreshErrorAlg, RepoCacheAlg, RepoCacheRepository} import org.scalasteward.core.repoconfig.RepoConfigAlg import org.scalasteward.core.scalafix.MigrationAlg import org.scalasteward.core.scalafmt.ScalafmtAlg import org.scalasteward.core.update.{FilterAlg, GroupMigrations, PruningAlg, UpdateAlg} import org.scalasteward.core.util._ import org.scalasteward.core.util.uri._ import org.scalasteward.core.vcs.data.AuthenticatedUser import org.scalasteward.core.vcs.{VCSApiAlg, VCSExtraAlg, VCSRepoAlg, VCSSelection} object Context { def create[F[_]: ConcurrentEffect: ContextShift: Parallel: Timer]( args: List[String] ): Resource[F, StewardAlg[F]] = for { blocker <- Blocker[F] cliArgs_ <- Resource.liftF(new Cli[F].parseArgs(args)) implicit0(config: Config) <- Resource.liftF(Config.create[F](cliArgs_)) implicit0(client: Client[F]) <- AsyncHttpClient.resource[F]() implicit0(logger: Logger[F]) <- Resource.liftF(Slf4jLogger.create[F]) implicit0(httpExistenceClient: HttpExistenceClient[F]) <- HttpExistenceClient.create[F] implicit0(user: AuthenticatedUser) <- Resource.liftF(config.vcsUser[F]) implicit0(fileAlg: FileAlg[F]) = FileAlg.create[F] implicit0(migrationAlg: MigrationAlg) <- Resource.liftF( MigrationAlg.create[F](config.scalafixMigrations) ) implicit0(groupMigration: GroupMigrations) <- Resource.liftF(GroupMigrations.create[F]) } yield { val kvsPrefix = Some(config.vcsType.asString) implicit val dateTimeAlg: DateTimeAlg[F] = DateTimeAlg.create[F] implicit val processAlg: ProcessAlg[F] = ProcessAlg.create[F](blocker) implicit val workspaceAlg: WorkspaceAlg[F] = WorkspaceAlg.create[F] implicit val repoConfigAlg: RepoConfigAlg[F] = new RepoConfigAlg[F] implicit val filterAlg: FilterAlg[F] = new FilterAlg[F] implicit val gitAlg: GitAlg[F] = GitAlg.create[F] implicit val httpJsonClient: HttpJsonClient[F] = new HttpJsonClient[F] implicit val repoCacheRepository: RepoCacheRepository[F] = new RepoCacheRepository[F](new JsonKeyValueStore("repo_cache", "1", kvsPrefix)) implicit val selfCheckAlg: SelfCheckAlg[F] = new SelfCheckAlg[F] val vcsSelection = new VCSSelection[F] implicit val vcsApiAlg: VCSApiAlg[F] = vcsSelection.getAlg(config) implicit val vcsRepoAlg: VCSRepoAlg[F] = VCSRepoAlg.create[F](config, gitAlg) implicit val vcsExtraAlg: VCSExtraAlg[F] = VCSExtraAlg.create[F] implicit val pullRequestRepository: PullRequestRepository[F] = new PullRequestRepository[F](new JsonKeyValueStore("pull_requests", "2", kvsPrefix)) implicit val scalafmtAlg: ScalafmtAlg[F] = ScalafmtAlg.create[F] implicit val coursierAlg: CoursierAlg[F] = CoursierAlg.create[F] implicit val versionsCache: VersionsCache[F] = new VersionsCache[F](config.cacheTtl, new JsonKeyValueStore("versions", "2")) implicit val updateAlg: UpdateAlg[F] = new UpdateAlg[F] implicit val mavenAlg: MavenAlg[F] = MavenAlg.create[F] implicit val sbtAlg: SbtAlg[F] = SbtAlg.create[F] implicit val millAlg: MillAlg[F] = MillAlg.create[F] implicit val buildToolDispatcher: BuildToolDispatcher[F] = BuildToolDispatcher.create[F] implicit val refreshErrorAlg: RefreshErrorAlg[F] = new RefreshErrorAlg[F](new JsonKeyValueStore("refresh_error", "1", kvsPrefix)) implicit val repoCacheAlg: RepoCacheAlg[F] = new RepoCacheAlg[F] implicit val editAlg: EditAlg[F] = new EditAlg[F] implicit val nurtureAlg: NurtureAlg[F] = new NurtureAlg[F] implicit val pruningAlg: PruningAlg[F] = new PruningAlg[F] new StewardAlg[F] } }
Example 49
Source File: Http4sClientEndpointsJsonSchemaTest.scala From endpoints4s with MIT License | 5 votes |
package endpoints4s.http4s.client import endpoints4s.algebra import endpoints4s.algebra.client import cats.effect.Sync import org.http4s.client.Client import cats.effect.IO import scala.concurrent.Future import scala.concurrent.ExecutionContext.global import org.http4s.client.asynchttpclient.AsyncHttpClient import cats.effect.ContextShift import endpoints4s.algebra.circe import org.http4s.Uri class TestJsonSchemaClient[F[_]: Sync](host: Uri, client: Client[F]) extends Endpoints[F](host, client) with BasicAuthentication with JsonEntitiesFromCodecs with algebra.BasicAuthenticationTestApi with algebra.EndpointsTestApi with algebra.JsonFromCodecTestApi with algebra.SumTypedEntitiesTestApi with circe.JsonFromCirceCodecTestApi with circe.JsonEntitiesFromCodecs class Http4sClientEndpointsJsonSchemaTest extends client.EndpointsTestSuite[TestJsonSchemaClient[IO]] with client.BasicAuthTestSuite[TestJsonSchemaClient[IO]] with client.JsonFromCodecTestSuite[TestJsonSchemaClient[IO]] with client.SumTypedEntitiesTestSuite[TestJsonSchemaClient[IO]] { implicit val ctx: ContextShift[IO] = IO.contextShift(global) val (ahc, shutdown) = AsyncHttpClient.allocate[IO]().unsafeRunSync() val client = new TestJsonSchemaClient[IO]( Uri.unsafeFromString(s"http://localhost:$wiremockPort"), ahc ) def call[Req, Resp]( endpoint: client.Endpoint[Req, Resp], args: Req ): Future[Resp] = { Thread.sleep(50) val eventualResponse = endpoint(args) Thread.sleep(50) eventualResponse.unsafeToFuture() } def encodeUrl[A](url: client.Url[A])(a: A): String = url.encodeUrl(a).toOption.get.renderString clientTestSuite() basicAuthSuite() jsonFromCodecTestSuite() override def afterAll(): Unit = { shutdown.unsafeRunSync() super.afterAll() } }
Example 50
Source File: Http4sClientSpec.scala From canoe with MIT License | 5 votes |
package canoe.api.clients import canoe.api._ import canoe.methods.Method import canoe.models.InputFile import cats.effect.IO import io.circe.{Decoder, Encoder} import org.http4s.HttpApp import org.http4s.client.Client import org.http4s.dsl.io._ import io.circe.Json import io.chrisdavenport.log4cats.slf4j.Slf4jLogger import org.scalatest.freespec.AnyFreeSpec class Http4sClientSpec extends AnyFreeSpec { private case class TestMethod(name: String = "test", encoder: Encoder[String] = Encoder.encodeString, decoder: Decoder[String] = Decoder.decodeString, files: List[InputFile] = Nil) extends Method[String, String] { def attachments(request: String): List[(String, InputFile)] = files.map("" -> _) } private implicit val testMethod = TestMethod() private def response(s: String) = s"""{"ok" : true, "result" : "$s"}""" private implicit val logger = Slf4jLogger.getLogger[IO] "Client" - { "sends" - { "to correct Telegram endpoint" in { val client: Client[IO] = Client.fromHttpApp(HttpApp(r => Ok(response(r.uri.toString)))) val tgClient = new Http4sTelegramClient("token", client) assert(tgClient.execute("any").unsafeRunSync() == s"https://api.telegram.org/bottoken/${testMethod.name}") } val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO] { r => Ok(response(r.headers.get(org.http4s.headers.`Content-Type`).map(_.value.replace("\"", "''")).getOrElse(""))) })) "json POST request if attachments contain file upload" in { assert(tgClient.execute("any").unsafeRunSync() == "application/json") } "multipart POST request if attachments contain file upload" in { val resp = tgClient.execute("any")(testMethod.copy(files = List(InputFile.Upload("", Array.emptyByteArray)))) assert(resp.unsafeRunSync().startsWith("multipart/form-data")) } } "encodes/decodes" - { "request entity with method encoder" in { val tgClient = new Http4sTelegramClient( "", Client.fromHttpApp(HttpApp[IO](_.bodyAsText.compile.string.flatMap(s => Ok(response(s.replace("\"", "'")))))) ) val res = tgClient.execute("")(testMethod.copy(encoder = Encoder.instance(_ => Json.fromString("encoded")))) assert(res.unsafeRunSync() == "'encoded'") } "result entity with method decoder" in { val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response(""))))) val res = tgClient.execute("")(testMethod.copy(decoder = Decoder.const("decoded"))) assert(res.unsafeRunSync() == "decoded") } } "handles" - { "decode failure as ResponseDecodingError" in { val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok("{}")))) assertThrows[ResponseDecodingError](tgClient.execute("any").unsafeRunSync()) } "unsuccessful result as FailedMethod" in { val response = """{"ok" : false, "result" : "any"}""" val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response)))) assertThrows[FailedMethod[String, String]](tgClient.execute("any").unsafeRunSync()) } } } }
Example 51
Source File: Http4sTelegramClient.scala From canoe with MIT License | 5 votes |
package canoe.api.clients import canoe.api.{FailedMethod, ResponseDecodingError, TelegramClient} import canoe.methods.Method import canoe.models.{InputFile, Response => TelegramResponse} import cats.effect.Sync import cats.syntax.all._ import fs2.Stream import io.chrisdavenport.log4cats.Logger import org.http4s._ import org.http4s.circe._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl._ import org.http4s.multipart.{Multipart, Part} private[api] class Http4sTelegramClient[F[_]: Sync: Logger](token: String, client: Client[F]) extends TelegramClient[F] { private val botApiUri: Uri = Uri.unsafeFromString("https://api.telegram.org") / s"bot$token" def execute[Req, Res](request: Req)(implicit M: Method[Req, Res]): F[Res] = { val req = prepareRequest(botApiUri / M.name, M, request) implicit val decoder: EntityDecoder[F, TelegramResponse[Res]] = jsonOf(Sync[F], TelegramResponse.decoder(M.decoder)) F.debug(s"Executing '${M.name}' Telegram method.") *> client .expect[TelegramResponse[Res]](req) .recoverWith { case error: InvalidMessageBodyFailure => handleUnknownEntity(M.name, request, error) } .flatMap(handleTelegramResponse(M, request)) } private def handleUnknownEntity[I, A](method: String, input: I, error: InvalidMessageBodyFailure): F[A] = F.error( s"Received unknown Telegram entity during execution of '$method' method. \nInput data: $input. \n${error.details}" ) *> ResponseDecodingError(error.details.dropWhile(_ != '{')).raiseError[F, A] private def prepareRequest[Req, Res](url: Uri, method: Method[Req, Res], action: Req): F[Request[F]] = { val uploads = method.attachments(action).collect { case (name, InputFile.Upload(filename, contents)) => Part.fileData(name, filename, Stream.emits(contents).covary[F]) } if (uploads.isEmpty) jsonRequest(url, method, action) else multipartRequest(url, method, action, uploads) } private def jsonRequest[Req, Res](url: Uri, method: Method[Req, Res], action: Req): F[Request[F]] = Method.POST(action, url)(F, jsonEncoderOf(method.encoder)) private def multipartRequest[Req, Res](url: Uri, method: Method[Req, Res], action: Req, parts: List[Part[F]]): F[Request[F]] = { val multipart = Multipart[F](parts.toVector) val params = method .encoder(action) .asObject .map( _.toIterable .filterNot(kv => kv._2.isNull || kv._2.isObject) .map { case (k, j) => k -> j.toString } .toMap ) .getOrElse(Map.empty) val urlWithQueryParams = params.foldLeft(url) { case (url, (key, value)) => url.withQueryParam(key, value) } Method.POST(multipart, urlWithQueryParams).map(_.withHeaders(multipart.headers)) } private def handleTelegramResponse[A, I, C](m: Method[I, A], input: I)(response: TelegramResponse[A]): F[A] = response match { case TelegramResponse(true, Some(result), _, _, _) => result.pure[F] case failed => F.error(s"Received failed response from Telegram: $failed. Method name: ${m.name}, input data: $input") *> FailedMethod(m, input, failed).raiseError[F, A] } }
Example 52
Source File: SolrUpdate.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.ftssolr import cats.effect._ import docspell.ftsclient._ import docspell.ftssolr.JsonCodec._ import _root_.io.circe._ import _root_.io.circe.syntax._ import org.http4s._ import org.http4s.circe._ import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl trait SolrUpdate[F[_]] { def add(tds: List[TextData]): F[Unit] def update(tds: List[TextData]): F[Unit] def delete(q: String, commitWithin: Option[Int]): F[Unit] } object SolrUpdate { def apply[F[_]: ConcurrentEffect](cfg: SolrConfig, client: Client[F]): SolrUpdate[F] = { val dsl = new Http4sClientDsl[F] {} import dsl._ new SolrUpdate[F] { val url = (Uri.unsafeFromString(cfg.url.asString) / "update") .withQueryParam("commitWithin", cfg.commitWithin.toString) .withQueryParam("overwrite", "true") .withQueryParam("wt", "json") def add(tds: List[TextData]): F[Unit] = { val req = Method.POST(tds.asJson, url) client.expect[Unit](req) } def update(tds: List[TextData]): F[Unit] = { val req = Method.POST(tds.filter(minOneChange).map(SetFields).asJson, url) client.expect[Unit](req) } def delete(q: String, commitWithin: Option[Int]): F[Unit] = { val uri = commitWithin match { case Some(n) => if (n <= 0) url.removeQueryParam("commitWithin").withQueryParam("commit", "true") else url.withQueryParam("commitWithin", n.toString) case None => url } val req = Method.POST(Delete(q).asJson, uri) client.expect[Unit](req) } private val minOneChange: TextData => Boolean = _ match { case td: TextData.Attachment => td.name.isDefined || td.text.isDefined case td: TextData.Item => td.name.isDefined || td.notes.isDefined } } } case class Delete(query: String) object Delete { implicit val jsonEncoder: Encoder[Delete] = new Encoder[Delete] { def apply(d: Delete): Json = Json.obj( ("delete", Json.obj("query" -> d.query.asJson)) ) } } }
Example 53
Source File: KamonSupport.scala From kamon-http4s with Apache License 2.0 | 5 votes |
package kamon.http4s package middleware.client import cats.effect.{Effect, Resource} import cats.implicits._ import com.typesafe.config.Config import kamon.Kamon import kamon.context.Context import kamon.instrumentation.http.HttpClientInstrumentation import org.http4s.{Request, Response} import org.http4s.client.Client object KamonSupport { private var _instrumentation = instrumentation(Kamon.config()) private def instrumentation(kamonConfig: Config): HttpClientInstrumentation = { val httpClientConfig = kamonConfig.getConfig("kamon.instrumentation.http4s.client") HttpClientInstrumentation.from(httpClientConfig, "http4s.client") } Kamon.onReconfigure(newConfig => _instrumentation = instrumentation(newConfig)) def apply[F[_]](underlying: Client[F])(implicit F:Effect[F]): Client[F] = Client { request => for { ctx <- Resource.liftF(F.delay(Kamon.currentContext())) k <- kamonClient(underlying)(request)(ctx)(_instrumentation) } yield k } private def kamonClient[F[_]](underlying: Client[F]) (request: Request[F]) (ctx: Context) (instrumentation: HttpClientInstrumentation) (implicit F:Effect[F]): Resource[F, Response[F]] = for { requestHandler <- Resource.liftF(F.delay(instrumentation.createHandler(getRequestBuilder(request), ctx))) response <- underlying.run(requestHandler.request).attempt trackedResponse <- Resource.liftF(handleResponse(response, requestHandler, instrumentation.settings)) } yield trackedResponse def handleResponse[F[_]]( response: Either[Throwable, Response[F]], requestHandler: HttpClientInstrumentation.RequestHandler[Request[F]], settings: HttpClientInstrumentation.Settings )(implicit F:Effect[F]): F[Response[F]] = response match { case Right(res) => if(res.status.code == 404) requestHandler.span.name(settings.defaultOperationName) requestHandler.processResponse(getResponseBuilder(res)) F.delay(res) case Left(error) => requestHandler.span.fail(error).finish() F.raiseError(error) } }
Example 54
Source File: JdkHttpClient.scala From http4s-jdk-http-client with Apache License 2.0 | 5 votes |
package org.http4s.client.jdkhttpclient import java.net.URI import java.net.http.HttpRequest.BodyPublishers import java.net.http.HttpResponse.BodyHandlers import java.net.http.{HttpClient, HttpRequest, HttpResponse} import java.nio.ByteBuffer import java.util import java.util.concurrent.Flow import cats.ApplicativeError import cats.effect._ import cats.implicits._ import fs2.concurrent.SignallingRef import fs2.interop.reactivestreams._ import fs2.{Chunk, Stream} import org.http4s.client.Client import org.http4s.client.jdkhttpclient.compat.CollectionConverters._ import org.http4s.internal.fromCompletionStage import org.http4s.util.CaseInsensitiveString import org.http4s.{Header, Headers, HttpVersion, Request, Response, Status} import org.reactivestreams.FlowAdapters object JdkHttpClient { def simple[F[_]](implicit F: ConcurrentEffect[F], CS: ContextShift[F]): F[Client[F]] = F.delay(HttpClient.newHttpClient()).map(apply(_)) def convertHttpVersionFromHttp4s[F[_]]( version: HttpVersion )(implicit F: ApplicativeError[F, Throwable]): F[HttpClient.Version] = version match { case HttpVersion.`HTTP/1.1` => HttpClient.Version.HTTP_1_1.pure[F] case HttpVersion.`HTTP/2.0` => HttpClient.Version.HTTP_2.pure[F] case _ => F.raiseError(new IllegalArgumentException("invalid HTTP version")) } // see jdk.internal.net.http.common.Utils#DISALLOWED_HEADERS_SET private val restrictedHeaders = Set( "connection", "content-length", "date", "expect", "from", "host", "upgrade", "via", "warning" ).map(CaseInsensitiveString(_)) }
Example 55
Source File: Dhall.scala From http4s-jdk-http-client with Apache License 2.0 | 5 votes |
import cats.effect._ import java.nio.file.{Files, Paths} import org.dhallj.core.Expr import org.dhallj.core.converters.JsonConverter import org.dhallj.imports.syntax._ import org.dhallj.parser.DhallParser import org.dhallj.yaml.YamlConverter import org.http4s.client.Client import org.http4s.client.jdkhttpclient.JdkHttpClient import sbt.{IO => _, _} import scala.concurrent.ExecutionContext import upickle.default.{ReadWriter, macroRW} object Dhall { lazy val convertDhall = taskKey[Unit]("Generate YAML/JSON from Dhall.") private lazy val http = { implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global) JdkHttpClient.simple[IO].unsafeRunSync() } private def loadDhall(expr: String): Expr = { implicit val c: Client[IO] = http DhallParser .parse(expr) .normalize() .resolveImports[IO] .unsafeRunSync() .normalize() } val convertDhallTask = convertDhall := { val baseDir = (Keys.baseDirectory in LocalRootProject).value.absolutePath def convertYaml(from: String, to: String): Unit = { val dhall = loadDhall(s"$baseDir/dhall/$from.dhall") val yaml = YamlConverter.toYamlString(dhall) Files.writeString(Paths.get(s"$baseDir/$to"), yaml) } List("ci", "release", "dhall").foreach { file => convertYaml(file, s".github/workflows/$file.yml") } convertYaml("mergify", s".mergify.yml") } case class ScalaVersions(default: String, all: List[String]) object ScalaVersions { implicit val rw: ReadWriter[ScalaVersions] = macroRW } val scalaVersions = settingKey[ScalaVersions]("Read the Scala versions via Dhall") val scalaVersionsImpl = scalaVersions := { val baseDir = (Keys.baseDirectory in LocalRootProject).value.absolutePath val dhall = loadDhall(s"$baseDir/dhall/scalaVersions.dhall") val json = JsonConverter.toCompactString(dhall) upickle.default.read[ScalaVersions](json) } }
Example 56
Source File: main.scala From seals with Apache License 2.0 | 5 votes |
package com.example.messaging import scala.concurrent.ExecutionContext.Implicits.global import cats.implicits._ import cats.effect.{ IO, IOApp, ExitCode } import org.http4s._ import org.http4s.dsl.io._ import org.http4s.client.Client import org.http4s.circe._ import org.http4s.server.blaze.BlazeServerBuilder import org.http4s.server.Router import org.http4s.implicits._ import dev.tauri.seals._ import dev.tauri.seals.circe.Codecs._ object Protocol { final case class Ping(seqNr: Long, payload: Vector[Int]) final case class Pong(seqNr: Long) final case class PingIncompatible(seqNr: Long, payload: Vector[Int], flags: Int) } object MyClient extends IOApp { import org.http4s.client.blaze._ import Protocol._ override def run(args: List[String]): IO[ExitCode] = { BlazeClientBuilder[IO](global).resource.use { client => for { pongGood <- ping(client, jsonEncoderOf[IO, Envelope[Ping]].toEntity( Envelope(Ping(42L, Vector(1, 2, 3, 4))) )) _ <- IO { assert(pongGood == Pong(42L)) } _ <- IO { println(pongGood) } pongBad <- ping(client, jsonEncoderOf[IO, Envelope[PingIncompatible]].toEntity( Envelope(PingIncompatible(99L, Vector(4, 5), 0)) )) _ <- IO { println(pongBad) } } yield ExitCode.Success } } def ping(client: Client[IO], ping: Entity[IO]): IO[Pong] = { for { pong <- client .expect(Request( POST, Uri(authority = Some(Uri.Authority(port = Some(1234))), path = "/test"), body = ping.body ))(jsonOf[IO, Envelope[Pong]]) } yield pong.value } } object MyServer extends IOApp { import org.http4s.server.blaze._ import Protocol._ val service = HttpRoutes.of[IO] { case p @ POST -> Root / "test" => for { env <- p.as(implicitly, jsonOf[IO, Envelope[Ping]]) resp <- Ok(Envelope(Pong(env.value.seqNr)))(implicitly, jsonEncoderOf) } yield resp } override def run(args: List[String]): IO[ExitCode] = { BlazeServerBuilder[IO] .bindHttp(1234, "localhost") .withHttpApp(Router("/" -> service).orNotFound) .serve .compile .drain .as(ExitCode.Success) } }
Example 57
Source File: Github.scala From sonar-scala with GNU Lesser General Public License v3.0 | 5 votes |
package com.mwz.sonar.scala package pr package github import cats.effect.Sync import cats.syntax.flatMap._ import com.mwz.sonar.scala.pr.github.Codec._ import io.circe.generic.auto._ import mouse.boolean._ import org.http4s.client.Client import org.http4s.{Header, Headers, Method, Request, Uri} trait Github[F[_]] { def authenticatedUser: F[User] def pullRequest: F[PullRequest] def comments: F[List[Comment]] def createComment(comment: NewComment): F[Unit] def files: F[List[File]] def createStatus(sha: String, status: NewStatus): F[Unit] } object Github { def apply[F[_]: Sync](client: Client[F], pr: GlobalConfig.PullRequest): Github[F] = new Github[F] { val auth: Header = Header("Authorization", s"token ${pr.github.oauth}") val userUri: Uri = pr.github.apiuri / "user" val prUri: Uri = (pr.github.apiuri / "repos").addPath(pr.github.repository) / "pulls" / pr.prNumber val commentsUri: Uri = prUri / "comments" val filesUri: Uri = prUri / "files" def newStatusUri(sha: String): Uri = (pr.github.apiuri / "repos").addPath(pr.github.repository) / "statuses" / sha def request(uri: Uri): Request[F] = { Request[F]( uri = uri, headers = Headers.of(auth) ) } def authenticatedUser: F[User] = client.expect[User](request(userUri)) def pullRequest: F[PullRequest] = client.expect[PullRequest](request(prUri)) def comments: F[List[Comment]] = client.expect[List[Comment]](request(commentsUri)) def createComment(comment: NewComment): F[Unit] = { val request: F[Request[F]] = Sync[F].pure( Request(Method.POST, commentsUri, headers = Headers.of(auth)) .withEntity(comment) ) pr.dryRun.fold(Sync[F].unit, client.expect[Comment](request) >> Sync[F].unit) } def files: F[List[File]] = client.expect[List[File]](request(filesUri)) def createStatus(sha: String, status: NewStatus): F[Unit] = { val request: F[Request[F]] = Sync[F].pure( Request(Method.POST, newStatusUri(sha), headers = Headers.of(auth)) .withEntity(status) ) pr.dryRun.fold(Sync[F].unit, client.expect[Status](request) >> Sync[F].unit) } } }
Example 58
Source File: TracingClient.scala From opencensus-scala with Apache License 2.0 | 5 votes |
package io.opencensus.scala.http4s import cats.effect.{Effect, Resource} import cats.implicits._ import io.opencensus.scala.Tracing import io.opencensus.scala.http.propagation.Propagation import io.opencensus.scala.http.{HttpAttributes => BaseHttpAttributes} import io.opencensus.scala.http4s.HttpAttributes._ import io.opencensus.scala.http4s.TracingUtils.recordResponse import io.opencensus.scala.http4s.propagation.Http4sFormatPropagation import io.opencensus.trace.{Span, Status} import org.http4s.client.Client import org.http4s.{Header, Request, Response} abstract class TracingClient[F[_]: Effect] { protected val tracing: Tracing protected val propagation: Propagation[Header, Request[F]] def trace(client: Client[F], parentSpan: Option[Span] = None): Client[F] = { val tracedOpen: Request[F] => Resource[F, Response[F]] = req => for { span <- Resource.liftF(startSpan(parentSpan, req)) enrichedReq = addTraceHeaders(req, span) res <- client .run(enrichedReq) .onError(traceError(span).andThen(x => Resource.liftF(x))) } yield recordResponse(span, tracing)(res) Client(tracedOpen) } private def traceError(span: Span): PartialFunction[Throwable, F[Unit]] = { case _ => recordException(span) } private def startSpan(parentSpan: Option[Span], req: Request[F]) = Effect[F].delay(startAndEnrichSpan(req, parentSpan)) private def startAndEnrichSpan( req: Request[F], parentSpan: Option[Span] ): Span = { val name = req.uri.path.toString val span = parentSpan.fold(tracing.startSpan(name))(span => tracing.startSpanWithParent(name, span) ) BaseHttpAttributes.setAttributesForRequest(span, req) span } private def addTraceHeaders(request: Request[F], span: Span): Request[F] = request.withHeaders( request.headers.put(propagation.headersWithTracingContext(span): _*) ) private def recordException(span: Span) = Effect[F].delay(tracing.endSpan(span, Status.INTERNAL)) } object TracingClient { def apply[F[_]: Effect]: TracingClient[F] = new TracingClient[F] { override protected val tracing: Tracing = Tracing override protected val propagation: Propagation[Header, Request[F]] = new Http4sFormatPropagation[F] {} } }
Example 59
Source File: MavenCentralClientTest.scala From zorechka-bot with MIT License | 5 votes |
package com.wix.zorechka.clients import com.wix.zorechka.{Dep, TestHelpers} import org.http4s.client.Client import zio.blocking.Blocking import zio.Task import zio.test._ object MavenCentralClientSpec extends DefaultRunnableSpec( suite("MavenCentralClientTest")( testM("return list of deps for an artifact") { val env = new Blocking.Live with MavenCentralClient.Live { override protected val httpClient: Client[Task] = TestHelpers.httpClient } val searchDep = Dep("org.scalacheck", "scalacheck_2.12", "1.10.0") for { result <- env.client.allVersions(searchDep) } yield assert(result, Assertion.equalTo(List("1.14.3", "1.14.2", "1.14.1", "1.14.1-RC2", "1.14.1-RC1", "1.14.0", "1.13.5", "1.12.6", "1.13.4", "1.11.6").map { version => searchDep.copy(version = version) })) } ) )
Example 60
Source File: TestHelpers.scala From zorechka-bot with MIT License | 5 votes |
package com.wix.zorechka import com.wix.zorechka.clients.Http4sClient import org.http4s.client.Client import zio.{Runtime, Task, ZIO} import zio.blocking.Blocking import zio.internal.PlatformLive object TestHelpers { def httpClient: Client[Task] = Runtime(Blocking.Live, PlatformLive.Default) .unsafeRunSync( ZIO.runtime[Blocking].flatMap { implicit rt => for { httpClientReservation <- Http4sClient.newHttpClient.reserve httpClient <- httpClientReservation.acquire } yield httpClient } ) .getOrElse(err => throw err.squash) }
Example 61
Source File: MavenCentralClient.scala From zorechka-bot with MIT License | 5 votes |
package com.wix.zorechka.clients import com.wix.zorechka.Dep import org.http4s.{EntityDecoder, Header, Headers, Method, Request, Uri} import zio.{Task, ZIO} import zio.interop.catz._ import io.circe.generic.auto._ import org.http4s.circe.jsonOf import org.http4s.client.Client trait MavenCentralClient { val client: MavenCentralClient.Service } object MavenCentralClient { trait Service { def allVersions(dep: Dep): Task[List[Dep]] } trait Live extends MavenCentralClient { protected val httpClient: Client[Task] val client = new MavenCentralClient.Service { case class Response(response: InnerResponse) case class InnerResponse(docs: Seq[Document]) case class Document(v: String) implicit val decoder: EntityDecoder[Task, Response] = jsonOf[Task, Response] override def allVersions(dep: Dep): Task[List[Dep]] = { ZIO.accessM { client => val uri = Uri .unsafeFromString("http://search.maven.org/solrsearch/select") .withQueryParam("rows", "10") .withQueryParam("core", "gav") .withQueryParam("q", s""" g:"${dep.groupId}" AND a:"${dep.artifactId}" """) println(s"Maven search: ${uri.renderString}") val request = Request[Task](Method.GET, uri, headers = Headers.of(Header("Accept", "application/json"))) httpClient.fetch(request)(response => response.as[Response]).map { _.response.docs.map(_.v).map(v => Dep(dep.groupId, dep.artifactId, v)).toList } } } } } }
Example 62
Source File: InternalWhitelistPilotGrader.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.plugins.pilotgraders import moe.pizza.auth.interfaces.PilotGrader import moe.pizza.auth.models.Pilot import moe.pizza.auth.models.Pilot.Status import moe.pizza.crestapi.CrestApi import moe.pizza.eveapi._ import org.http4s.client.Client import scala.concurrent.ExecutionContext import scala.util.Try class InternalWhitelistPilotGrader(c: CrestApi, ids: List[Long])( implicit val client: Client) extends PilotGrader { override def grade(p: Pilot): Status.Value = { p.getCrestTokens.flatMap { t => Try { c.refresh(t.token).unsafePerformSync }.toOption }.map { f => val verify = c.verify(f.access_token).unsafePerformSync verify.CharacterID }.find { ids.contains } match { case Some(k) => Status.internal case None => Status.unclassified } } }
Example 63
Source File: Http4sTextPlainTest.scala From guardrail with MIT License | 5 votes |
package generators.Http4s.Client.contentType import _root_.tests.contentTypes.textPlain.client.http4s.foo.FooClient import _root_.tests.contentTypes.textPlain.client.{ http4s => cdefs } import _root_.tests.contentTypes.textPlain.server.http4s.foo.{ DoBarResponse, DoBazResponse, DoFooResponse, FooHandler, FooResource } import _root_.tests.contentTypes.textPlain.server.{ http4s => sdefs } import org.scalatest.{ EitherValues, FunSuite, Matchers } import org.http4s.dsl.io._ import org.http4s.headers._ import cats.effect.IO import org.http4s.client.Client import org.http4s.{ Charset, HttpRoutes, MediaType } class Http4sTextPlainTest extends FunSuite with Matchers with EitherValues { import org.http4s.implicits._ test("Plain text should be emitted for required parameters (raw)") { val route: HttpRoutes[IO] = HttpRoutes.of { case req @ POST -> Root / "foo" => if (req.contentType.contains(`Content-Type`(MediaType.text.plain, Charset.`UTF-8`))) { for { value <- req.as[String] resp <- if (value == "sample") Created() else NotAcceptable() } yield resp } else NotAcceptable() } val client: Client[IO] = Client.fromHttpApp(route.orNotFound) val fooClient = FooClient.httpClient(client) fooClient.doFoo("sample").attempt.unsafeRunSync().right.value shouldBe cdefs.foo.DoFooResponse.Created } test("Plain text should be emitted for optional parameters (raw)") { val route: HttpRoutes[IO] = HttpRoutes.of { case req @ POST -> Root / "bar" => if (req.contentType.contains(`Content-Type`(MediaType.text.plain, Charset.`UTF-8`))) { for { value <- req.as[String] resp <- if (value == "sample") Created() else NotAcceptable() } yield resp } else NotAcceptable() } val client: Client[IO] = Client.fromHttpApp(route.orNotFound) val fooClient = FooClient.httpClient(client) fooClient.doBar(Some("sample")).attempt.unsafeRunSync().right.value shouldBe cdefs.foo.DoBarResponse.Created } test("Plain text should be emitted for required parameters") { val route: HttpRoutes[IO] = new FooResource[IO]().routes(new FooHandler[IO] { def doFoo(respond: DoFooResponse.type)(body: String): IO[sdefs.foo.DoFooResponse] = if (body == "sample") { IO.pure(respond.Created) } else { IO.pure(respond.NotAcceptable) } def doBar(respond: DoBarResponse.type)(body: Option[String]): IO[sdefs.foo.DoBarResponse] = ??? def doBaz(respond: DoBazResponse.type)(body: Option[String]): IO[sdefs.foo.DoBazResponse] = ??? }) val client: Client[IO] = Client.fromHttpApp(route.orNotFound) val fooClient = FooClient.httpClient(client) fooClient.doFoo("sample").attempt.unsafeRunSync().right.value shouldBe cdefs.foo.DoFooResponse.Created } test("Plain text should be emitted for present optional parameters") { val route: HttpRoutes[IO] = new FooResource[IO]().routes(new FooHandler[IO] { def doFoo(respond: DoFooResponse.type)(body: String): IO[sdefs.foo.DoFooResponse] = ??? def doBar(respond: DoBarResponse.type)(body: Option[String]): IO[sdefs.foo.DoBarResponse] = if (body.contains("sample")) { IO.pure(respond.Created) } else { IO.pure(respond.NotAcceptable) } def doBaz(respond: DoBazResponse.type)(body: Option[String]): IO[sdefs.foo.DoBazResponse] = ??? }) val client: Client[IO] = Client.fromHttpApp(route.orNotFound) val fooClient = FooClient.httpClient(client) fooClient.doBar(Some("sample")).attempt.unsafeRunSync().right.value shouldBe cdefs.foo.DoBarResponse.Created } test("Plain text should be emitted for missing optional parameters") { val route: HttpRoutes[IO] = new FooResource[IO]().routes(new FooHandler[IO] { def doFoo(respond: DoFooResponse.type)(body: String): IO[sdefs.foo.DoFooResponse] = ??? def doBar(respond: DoBarResponse.type)(body: Option[String]): IO[sdefs.foo.DoBarResponse] = if (body.isEmpty) { IO.pure(respond.Created) } else { IO.pure(respond.NotAcceptable) } def doBaz(respond: DoBazResponse.type)(body: Option[String]): IO[sdefs.foo.DoBazResponse] = ??? }) val client: Client[IO] = Client.fromHttpApp(route.orNotFound) val fooClient = FooClient.httpClient(client) fooClient.doBar(None).attempt.unsafeRunSync().right.value shouldBe cdefs.foo.DoBarResponse.Created } }
Example 64
Source File: ProjectClientSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import java.util.UUID import cats.effect.IO import cats.effect.concurrent.Ref import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.{AbstractCliSpec, Console} import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.ClientStatusError import ch.epfl.bluebrain.nexus.cli.config.{AppConfig, EnvConfig} import ch.epfl.bluebrain.nexus.cli.sse._ import ch.epfl.bluebrain.nexus.cli.utils.Http4sExtras import izumi.distage.model.definition.ModuleDef import org.http4s.circe.CirceEntityEncoder._ import org.http4s.client.Client import org.http4s.dsl.io._ import org.http4s.{HttpApp, Response, Status} class ProjectClientSpec extends AbstractCliSpec with Http4sExtras { private val projectJson = jsonContentOf("/templates/project.json", replacements) type Cache = Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)] type CacheRef = Ref[IO, Cache] override def overrides: ModuleDef = new ModuleDef { include(defaultModules) make[Client[IO]].from { cfg: AppConfig => val token = cfg.env.token val httpApp = HttpApp[IO] { case GET -> `v1` / "projects" / OrgUuidVar(`orgUuid`) / ProjectUuidVar(`projectUuid`) optbearer `token` => Response[IO](Status.Ok).withEntity(projectJson).pure[IO] case GET -> `v1` / "projects" / OrgUuidVar(_) / ProjectUuidVar(_) optbearer `token` => Response[IO](Status.NotFound).withEntity(notFoundJson).pure[IO] case GET -> `v1` / "projects" / OrgUuidVar(_) / ProjectUuidVar(_) bearer (_: BearerToken) => Response[IO](Status.Forbidden).withEntity(authFailedJson).pure[IO] } Client.fromHttpApp(httpApp) } make[CacheRef].fromEffect { Ref.of[IO, Cache](Map.empty) } } "A ProjectClient" should { "resolve a known (orgUuid, projUuid) pair" in { (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) => val cl = ProjectClient[IO](client, env, cache, console) for { labels <- cl.labels(orgUuid, projectUuid) _ = labels shouldEqual Right((orgLabel, projectLabel)) } yield () } "resolve from cache a known (orgUuid, projUuid) pair" in { (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) => val errClient = Client.fromHttpApp(HttpApp[IO] { case GET -> Root => IO.pure(Response[IO](Status.NotFound)) }) for { _ <- ProjectClient[IO](client, env, cache, console).labels(orgUuid, projectUuid) labels <- ProjectClient[IO](errClient, env, cache, console).labels(orgUuid, projectUuid) _ = labels shouldEqual Right((orgLabel, projectLabel)) } yield () } "fail to resolve an unknown (orgUuid, projUuid) pair" in { (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) => val cl = ProjectClient[IO](client, env, cache, console) for { labels <- cl.labels(OrgUuid(UUID.randomUUID()), projectUuid) _ = labels shouldEqual Left(ClientStatusError(Status.NotFound, notFoundJson.noSpaces)) } yield () } "fail to resolve a known (orgUuid, projUuid) pair with bad credentials" in { (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) => val cl = ProjectClient[IO](client, env.copy(token = Some(BearerToken("bad"))), cache, console) for { labels <- cl.labels(orgUuid, projectUuid) _ = labels shouldEqual Left(ClientStatusError(Status.Forbidden, authFailedJson.noSpaces)) } yield () } } }
Example 65
Source File: SparqlClientSpec.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import cats.effect.IO import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.{AbstractCliSpec, Console} import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.{ClientStatusError, ServerStatusError} import ch.epfl.bluebrain.nexus.cli.config.{AppConfig, EnvConfig} import ch.epfl.bluebrain.nexus.cli.sse._ import ch.epfl.bluebrain.nexus.cli.utils.Http4sExtras import izumi.distage.model.definition.ModuleDef import org.http4s.circe.CirceEntityEncoder._ import org.http4s.client.Client import org.http4s.dsl.io._ import org.http4s.headers.`Content-Type` import org.http4s.{HttpApp, Response, Status, Uri} import org.scalatest.OptionValues class SparqlClientSpec extends AbstractCliSpec with Http4sExtras with OptionValues { private val sparqlResultsJson = jsonContentOf("/templates/sparql-results.json") private val sparqlResults = sparqlResultsJson.as[SparqlResults].toOption.value private val query = "SELECT * {?s ?p ?o} LIMIT 10" override def overrides: ModuleDef = new ModuleDef { include(defaultModules) make[Client[IO]].from { cfg: AppConfig => val token = cfg.env.token val ct = `Content-Type`(SparqlClient.`application/sparql-query`) val view = cfg.env.defaultSparqlView.renderString val httpApp = HttpApp[IO] { // success case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar( `projectLabel` ) / `view` / "sparql" contentType `ct` optbearer `token` => req.as[String].flatMap { case `query` => Response[IO](Status.Ok).withEntity(sparqlResultsJson).pure[IO] case _ => Response[IO](Status.BadRequest).pure[IO] } // unknown view id case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar( `projectLabel` ) / (_: String) / "sparql" contentType `ct` optbearer `token` => req.as[String].flatMap { case `query` => Response[IO](Status.NotFound).withEntity(notFoundJson).pure[IO] case _ => Response[IO](Status.BadRequest).pure[IO] } // unknown token case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar( `projectLabel` ) / `view` / "sparql" contentType `ct` optbearer (_: Option[ BearerToken ]) => req.as[String].flatMap { case `query` => Response[IO](Status.Forbidden).withEntity(authFailedJson).pure[IO] case _ => Response[IO](Status.BadRequest).pure[IO] } // other - internal error case req @ POST -> "v1" /: (_: Path) contentType `ct` optbearer `token` => req.as[String].flatMap { case `query` => Response[IO](Status.InternalServerError).withEntity(internalErrorJson).pure[IO] case _ => Response[IO](Status.BadRequest).pure[IO] } } Client.fromHttpApp(httpApp) } } "A SparqlClient" should { "return sparql results" in { (client: Client[IO], console: Console[IO], env: EnvConfig) => val cl = SparqlClient(client, env, console) for { results <- cl.query(orgLabel, projectLabel, query) _ = results shouldEqual Right(sparqlResults) } yield () } "return not found" in { (client: Client[IO], console: Console[IO], env: EnvConfig) => val cl = SparqlClient(client, env, console) for { results <- cl.query(orgLabel, projectLabel, Uri.unsafeFromString(genString()), query) _ = results shouldEqual Left(ClientStatusError(Status.NotFound, notFoundJson.noSpaces)) } yield () } "return internal error" in { (client: Client[IO], console: Console[IO], env: EnvConfig) => val cl = SparqlClient(client, env, console) for { results <- cl.query(orgLabel, ProjectLabel(genString()), Uri.unsafeFromString(genString()), query) _ = results shouldEqual Left(ServerStatusError(Status.InternalServerError, internalErrorJson.noSpaces)) } yield () } "return bad token" in { (client: Client[IO], console: Console[IO], env: EnvConfig) => val cl = SparqlClient(client, env.copy(token = Some(BearerToken("bad"))), console) for { results <- cl.query(orgLabel, projectLabel, query) _ = results shouldEqual Left(ClientStatusError(Status.Forbidden, authFailedJson.noSpaces)) } yield () } } }
Example 66
Source File: InfluxClient.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import cats.effect.{Sync, Timer} import cats.implicits._ import ch.epfl.bluebrain.nexus.cli._ import ch.epfl.bluebrain.nexus.cli.config.influx.InfluxConfig import ch.epfl.bluebrain.nexus.cli.config.{AppConfig, EnvConfig} import io.circe.Json import org.http4s.client.Client import org.http4s.{Method, Request, UrlForm} trait InfluxClient[F[_]] { final def apply[F[_]: Sync: Timer]( client: Client[F], config: AppConfig, console: Console[F] ): InfluxClient[F] = { implicit val c: Console[F] = console new LiveInfluxDbClient[F](client, config.influx, config.env) } }
Example 67
Source File: ProjectClient.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import cats.effect.concurrent.Ref import cats.effect.{Sync, Timer} import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.config.EnvConfig import ch.epfl.bluebrain.nexus.cli.sse.{OrgLabel, OrgUuid, ProjectLabel, ProjectUuid} import ch.epfl.bluebrain.nexus.cli.{ClientErrOr, Console} import io.circe.Decoder import io.circe.generic.semiauto.deriveDecoder import org.http4s.client.Client import org.http4s.{Headers, Request} trait ProjectClient[F[_]] { final def apply[F[_]: Sync: Timer]( client: Client[F], env: EnvConfig, cache: Ref[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]], console: Console[F] ): ProjectClient[F] = { implicit val c: Console[F] = console new LiveProjectClient[F](client, env, cache) } private class LiveProjectClient[F[_]: Timer: Console: Sync]( client: Client[F], env: EnvConfig, cache: Ref[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]] ) extends AbstractHttpClient[F](client, env) with ProjectClient[F] { override def labels(org: OrgUuid, proj: ProjectUuid): F[ClientErrOr[(OrgLabel, ProjectLabel)]] = cache.get.flatMap { map => map.get((org, proj)) match { // value in cache, return case Some(value) => F.pure(Right(value)) // value not in cache, fetch, update and return case None => get(org, proj).flatMap { // propagate error case l @ Left(_) => F.pure(l) // success, update cache and return case r @ Right(value) => cache.modify(m => (m.updated((org, proj), value), value)) *> F.pure(r) } } } private def get(org: OrgUuid, proj: ProjectUuid): F[ClientErrOr[(OrgLabel, ProjectLabel)]] = { val uri = env.project(org, proj) val req = Request[F](uri = uri, headers = Headers(env.authorizationHeader.toList)) executeParse[NexusAPIProject](req).map { case Right(NexusAPIProject(orgLabel, projectLabel)) => Right((orgLabel, projectLabel)) case Left(err) => Left(err) } } } final private[ProjectClient] case class NexusAPIProject(`_organizationLabel`: OrgLabel, `_label`: ProjectLabel) private[ProjectClient] object NexusAPIProject { implicit val nexusAPIProjectDecoder: Decoder[NexusAPIProject] = deriveDecoder[NexusAPIProject] } }
Example 68
Source File: SparqlClient.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import cats.effect.{Sync, Timer} import ch.epfl.bluebrain.nexus.cli.config.EnvConfig import ch.epfl.bluebrain.nexus.cli.sse.{OrgLabel, ProjectLabel} import ch.epfl.bluebrain.nexus.cli.{ClientErrOr, Console} import org.http4s._ import org.http4s.client.Client import org.http4s.headers.`Content-Type` trait SparqlClient[F[_]] { final def apply[F[_]: Sync: Timer](client: Client[F], env: EnvConfig, console: Console[F]): SparqlClient[F] = { implicit val c: Console[F] = console new LiveSparqlClient[F](client, env) } final val `application/sparql-query`: MediaType = new MediaType("application", "sparql-query") final private class LiveSparqlClient[F[_]: Timer: Console: Sync](client: Client[F], env: EnvConfig) extends AbstractHttpClient(client, env) with SparqlClient[F] { override def query( org: OrgLabel, proj: ProjectLabel, view: Option[Uri], queryStr: String ): F[ClientErrOr[SparqlResults]] = { val uri = env.sparql(org, proj, view.getOrElse(env.defaultSparqlView)) val headers = Headers(env.authorizationHeader.toList) val req = Request[F](method = Method.POST, uri = uri, headers = headers) .withEntity(queryStr) .withContentType(`Content-Type`(`application/sparql-query`)) executeParse[SparqlResults](req) } } }
Example 69
Source File: AbstractHttpClient.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.clients import cats.effect.{Sync, Timer} import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.CliError.ClientError import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.{SerializationError, Unexpected} import ch.epfl.bluebrain.nexus.cli.config.EnvConfig import ch.epfl.bluebrain.nexus.cli.{logRetryErrors, ClientErrOr, Console} import io.circe.Decoder import org.http4s.circe.CirceEntityDecoder._ import org.http4s.client.Client import org.http4s.{Request, Response} import retry.CatsEffect._ import retry.RetryPolicy import retry.syntax.all._ import scala.reflect.ClassTag import scala.util.control.NonFatal class AbstractHttpClient[F[_]: Timer](client: Client[F], env: EnvConfig)(implicit protected val F: Sync[F], protected val console: Console[F] ) { protected val retry = env.httpClient.retry protected def successCondition[A] = retry.condition.notRetryFromEither[A] _ implicit protected val retryPolicy: RetryPolicy[F] = retry.retryPolicy implicit protected def logOnError[A] = logRetryErrors[F, A]("interacting with an HTTP API") protected def executeDiscard[A](req: Request[F], returnValue: => A): F[ClientErrOr[A]] = execute(req, _.body.compile.drain.as(Right(returnValue))) protected def executeParse[A: Decoder](req: Request[F])(implicit A: ClassTag[A]): F[ClientErrOr[A]] = execute( req, _.attemptAs[A].value.map( _.leftMap(err => SerializationError(err.message, s"The response payload was not of type '${A.runtimeClass.getSimpleName}'") ) ) ) private def execute[A](req: Request[F], f: Response[F] => F[ClientErrOr[A]]): F[ClientErrOr[A]] = client .fetch(req)(ClientError.errorOr[F, A](r => f(r))) .recoverWith { case NonFatal(err) => F.delay(Left(Unexpected(Option(err.getMessage).getOrElse("").take(30)))) } .retryingM(successCondition[A]) }
Example 70
Source File: CliModule.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli import cats.effect.concurrent.Ref import cats.effect.{ConcurrentEffect, Timer} import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.clients._ import ch.epfl.bluebrain.nexus.cli.config.AppConfig import ch.epfl.bluebrain.nexus.cli.sse.{OrgLabel, OrgUuid, ProjectLabel, ProjectUuid} import distage.{ModuleDef, TagK} import izumi.distage.model.definition.StandardAxis.Repo import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import scala.concurrent.ExecutionContext import scala.concurrent.duration.Duration final class CliModule[F[_]: ConcurrentEffect: Timer: TagK] extends ModuleDef { make[Console[F]].tagged(Repo.Prod).from(Console[F]) make[Client[F]].tagged(Repo.Prod).fromResource { BlazeClientBuilder[F](ExecutionContext.global).withIdleTimeout(Duration.Inf).resource } make[ProjectClient[F]].tagged(Repo.Prod).fromEffect { (cfg: AppConfig, client: Client[F], console: Console[F]) => Ref.of[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]](Map.empty).map { cache => ProjectClient(client, cfg.env, cache, console) } } make[SparqlClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], console: Console[F]) => SparqlClient(client, cfg.env, console) } make[EventStreamClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], pc: ProjectClient[F]) => EventStreamClient(client, pc, cfg.env) } make[InfluxClient[F]].tagged(Repo.Prod).from { (cfg: AppConfig, client: Client[F], console: Console[F]) => InfluxClient(client, cfg, console) } } object CliModule { final def apply[F[_]: ConcurrentEffect: Timer: TagK]: CliModule[F] = new CliModule[F] }
Example 71
Source File: CrestKeyGrader.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.plugins.pilotgraders import moe.pizza.auth.interfaces.PilotGrader import moe.pizza.auth.models.Pilot import moe.pizza.auth.models.Pilot.Status import moe.pizza.crestapi.CrestApi import org.http4s.client.Client import scala.util.Try class CrestKeyGrader(c: CrestApi)(implicit val client: Client) extends PilotGrader { override def grade(p: Pilot): Status.Value = { p.getCrestTokens.flatMap { t => Try { c.refresh(t.token).unsafePerformSync }.toOption }.map { f => val verify = c.verify(f.access_token).unsafePerformSync verify.CharacterName }.find { _ == p.characterName } match { case Some(k) => Status.unclassified case None => Status.expired } } }
Example 72
Source File: HttpClients.scala From iotchain with MIT License | 5 votes |
package jbok.network.http.client import cats.effect._ import javax.net.ssl.SSLContext import jbok.common.thread.ThreadUtil import jbok.network.http.client.middleware.{LoggerMiddleware, MetricsMiddleware, RetryMiddleware} import okhttp3.OkHttpClient import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import org.http4s.client.okhttp.OkHttpBuilder object HttpClients { def withMiddlewares[F[_]](client: Client[F])(implicit F: Concurrent[F], T: Timer[F]): F[Client[F]] = MetricsMiddleware(LoggerMiddleware()(RetryMiddleware()(client))) def okHttp[F[_]](sslContext: Option[SSLContext] = None)(implicit F: ConcurrentEffect[F], cs: ContextShift[F]): Resource[F, Client[F]] = ThreadUtil.blockingThreadPool[F]("jbok-okhttp-client").flatMap { blockEC => val builder = sslContext match { case Some(ctx) => new OkHttpClient.Builder().sslSocketFactory(ctx.getSocketFactory) case None => new OkHttpClient.Builder() } OkHttpBuilder[F](builder.build(), blockEC).resource } def blaze[F[_]](sslContext: Option[SSLContext] = None)(implicit F: ConcurrentEffect[F]): Resource[F, Client[F]] = ThreadUtil.blockingThreadPool[F]("jbok-blaze-client").flatMap { blockEC => BlazeClientBuilder[F](blockEC) .withSslContextOption(sslContext) .resource } }
Example 73
Source File: CaldariCrestKeyGrader.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.plugins.pilotgraders import moe.pizza.auth.interfaces.PilotGrader import moe.pizza.auth.models.Pilot import moe.pizza.auth.models.Pilot.Status import moe.pizza.crestapi.CrestApi import moe.pizza.eveapi.{EVEAPI} import org.http4s.client.Client import scala.util.Try class CaldariCrestKeyGrader(c: CrestApi, eve: Option[EVEAPI] = None)( implicit val client: Client) extends PilotGrader { val eveapi = eve.getOrElse(new EVEAPI(client)) override def grade(p: Pilot): Status.Value = { p.getCrestTokens.flatMap { t => Try { c.refresh(t.token).unsafePerformSync }.toOption }.map { f => val verify = c.verify(f.access_token).unsafePerformSync verify.CharacterID }.exists { id => eveapi.char.CharacterInfo(id.toInt).unsafePerformSync.result.race == "Caldari" } match { case true => // caldari is the enemy Status.banned case false => // non-caldari is okay Status.unclassified } } }
Example 74
Source File: LocationManager.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.plugins import moe.pizza.auth.models.Pilot import moe.pizza.crestapi.CrestApi import moe.pizza.eveapi._ import org.http4s.client.Client object LocationManager { def locateUsers(crest: CrestApi)(pilots: List[Pilot])( implicit client: Client) = { pilots.map { p => p.getCrestTokens.map { token => val refreshed = crest.refresh(token.token).unsafePerformSync val verify = crest.verify(refreshed.access_token).unsafePerformSync (p, verify.CharacterName, crest.character.location(token.characterID, refreshed.access_token)) } } } }
Example 75
Source File: ConfigFile.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.config import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.JsonNode import moe.pizza.auth.adapters.GraderChain import moe.pizza.auth.adapters.PilotGraderLike.PilotGraderFactory import moe.pizza.auth.interfaces.PilotGrader import moe.pizza.auth.webapp.oauth.OAuthApplication import scala.concurrent.ExecutionContext import org.http4s.client.Client object ConfigFile { case class PingBotConfig( host: String, password: String ) case class EmbeddedLdapConfig( instancePath: String = "./ldap", port: Int = 389, basedn: String = "ou=pizza", host: String = "localhost", password: Option[String] = None ) case class AuthGroupConfig(closed: List[String], open: List[String], public: List[String]) case class AuthConfig( domain: String, corporation: String, alliance: String, groupName: String, groupShortName: String, groups: AuthGroupConfig, graders: List[JsonNode], pingbot: Option[PingBotConfig], restkeys: List[String], applications: List[OAuthApplication] = List() ) { def constructGraders(c: ConfigFile)( implicit client: Client): PilotGrader = new GraderChain( graders.map(g => PilotGraderFactory.fromYaml(g, c)).flatten.toList) } case class CrestConfig( @JsonProperty("login_url") loginUrl: String, @JsonProperty("crest_url") crestUrl: String, clientID: String, secretKey: String, redirectUrl: String ) case class ConfigFile( crest: CrestConfig, auth: AuthConfig, embeddedldap: EmbeddedLdapConfig ) }
Example 76
Source File: Update.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.tasks import moe.pizza.auth.interfaces.PilotGrader import moe.pizza.auth.models.Pilot import moe.pizza.crestapi.CrestApi import moe.pizza.eveapi._ import org.http4s.client.Client import scala.util.Try class Update(crest: CrestApi, eveapi: EVEAPI, chain: PilotGrader)( implicit val client: Client) { def updateUser(p: Pilot): Pilot = { val keys = p.getCrestTokens val mainkey = keys.head Try { val charinfo = eveapi.eve.CharacterInfo(mainkey.characterID).unsafePerformSync val refreshed = crest.refresh(mainkey.token).unsafePerformSync val corpAndAlliance = charinfo match { case Left(r) => (r.result.corporation, "") case Right(r) => (r.result.corporation, r.result.alliance) } val pilotWithUpdatedMembership = p.copy(corporation = corpAndAlliance._1, alliance = corpAndAlliance._2) val gradedPilot = pilotWithUpdatedMembership.copy( accountStatus = chain.grade(pilotWithUpdatedMembership)) gradedPilot }.getOrElse(p.copy(accountStatus = Pilot.Status.banned)) } }
Example 77
Source File: UserRegistry.scala From http4s-tracer with Apache License 2.0 | 5 votes |
package dev.profunktor.tracer.http package client import cats.effect.Sync import cats.syntax.functor._ import dev.profunktor.tracer.model.user.User import io.circe.syntax._ import org.http4s.Method._ import org.http4s.Uri import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl trait UserRegistry[F[_]] { def register(user: User): F[Unit] } final case class LiveUserRegistry[F[_]: Sync]( client: Client[F] ) extends UserRegistry[F] with Http4sClientDsl[F] { private val uri = Uri.uri("https://jsonplaceholder.typicode.com/posts") def register(user: User): F[Unit] = client.successful(POST(user.asJson, uri)).void }
Example 78
Source File: TracedHttpClients.scala From http4s-tracer with Apache License 2.0 | 5 votes |
package dev.profunktor.tracer.module.tracer import cats.effect.Sync import cats.syntax.apply._ import dev.profunktor.tracer.Trace.Trace import dev.profunktor.tracer.http.client.UserRegistry import dev.profunktor.tracer.model.user.User import dev.profunktor.tracer.module.{HttpClients, LiveHttpClients} import dev.profunktor.tracer.{Trace, TracerLog} import org.http4s.client.Client case class TracedHttpClients[F[_]: Sync: λ[T[_] => TracerLog[Trace[T, ?]]]] private ( client: Client[F] ) extends HttpClients[Trace[F, ?]] { private val clients = LiveHttpClients[F](client) override val userRegistry: UserRegistry[Trace[F, ?]] = new TracedUserRegistry[F](clients.userRegistry) } private[tracer] final class TracedUserRegistry[F[_]: Sync]( registry: UserRegistry[F] )(implicit L: TracerLog[Trace[F, ?]]) extends UserRegistry[Trace[F, ?]] { override def register(user: User): Trace[F, Unit] = L.info[UserRegistry[F]](s"Registering user: ${user.username.value}") *> Trace(_ => registry.register(user)) }
Example 79
Source File: BackendApp.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.backend import scala.concurrent.ExecutionContext import cats.effect._ import docspell.backend.auth.Login import docspell.backend.ops._ import docspell.backend.signup.OSignup import docspell.ftsclient.FtsClient import docspell.joexapi.client.JoexClient import docspell.store.Store import docspell.store.queue.JobQueue import docspell.store.usertask.UserTaskStore import emil.javamail.{JavaMailEmil, Settings} import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder trait BackendApp[F[_]] { def login: Login[F] def signup: OSignup[F] def collective: OCollective[F] def source: OSource[F] def tag: OTag[F] def equipment: OEquipment[F] def organization: OOrganization[F] def upload: OUpload[F] def node: ONode[F] def job: OJob[F] def item: OItem[F] def itemSearch: OItemSearch[F] def fulltext: OFulltext[F] def mail: OMail[F] def joex: OJoex[F] def userTask: OUserTask[F] } object BackendApp { def create[F[_]: ConcurrentEffect: ContextShift]( cfg: Config, store: Store[F], httpClient: Client[F], ftsClient: FtsClient[F], blocker: Blocker ): Resource[F, BackendApp[F]] = for { utStore <- UserTaskStore(store) queue <- JobQueue(store) loginImpl <- Login[F](store) signupImpl <- OSignup[F](store) collImpl <- OCollective[F](store) sourceImpl <- OSource[F](store) tagImpl <- OTag[F](store) equipImpl <- OEquipment[F](store) orgImpl <- OOrganization(store) joexImpl <- OJoex(JoexClient(httpClient), store) uploadImpl <- OUpload(store, queue, cfg.files, joexImpl) nodeImpl <- ONode(store) jobImpl <- OJob(store, joexImpl) itemImpl <- OItem(store, ftsClient) itemSearchImpl <- OItemSearch(store) fulltextImpl <- OFulltext(itemSearchImpl, ftsClient, store, queue, joexImpl) javaEmil = JavaMailEmil(blocker, Settings.defaultSettings.copy(debug = cfg.mailDebug)) mailImpl <- OMail(store, javaEmil) userTaskImpl <- OUserTask(utStore, queue, joexImpl) } yield new BackendApp[F] { val login: Login[F] = loginImpl val signup: OSignup[F] = signupImpl val collective: OCollective[F] = collImpl val source = sourceImpl val tag = tagImpl val equipment = equipImpl val organization = orgImpl val upload = uploadImpl val node = nodeImpl val job = jobImpl val item = itemImpl val itemSearch = itemSearchImpl val fulltext = fulltextImpl val mail = mailImpl val joex = joexImpl val userTask = userTaskImpl } def apply[F[_]: ConcurrentEffect: ContextShift]( cfg: Config, connectEC: ExecutionContext, httpClientEc: ExecutionContext, blocker: Blocker )(ftsFactory: Client[F] => Resource[F, FtsClient[F]]): Resource[F, BackendApp[F]] = for { store <- Store.create(cfg.jdbc, connectEC, blocker) httpClient <- BlazeClientBuilder[F](httpClientEc).resource ftsClient <- ftsFactory(httpClient) backend <- create(cfg, store, httpClient, ftsClient, blocker) } yield backend }
Example 80
Source File: JoexClient.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.joexapi.client import scala.concurrent.ExecutionContext import cats.effect._ import cats.implicits._ import docspell.common.syntax.all._ import docspell.common.{Ident, LenientUri} import docspell.joexapi.model.BasicResult import org.http4s.circe.CirceEntityDecoder._ import org.http4s.client.Client import org.http4s.client.blaze.BlazeClientBuilder import org.http4s.{Method, Request, Uri} import org.log4s.getLogger trait JoexClient[F[_]] { def notifyJoex(base: LenientUri): F[Unit] def notifyJoexIgnoreErrors(base: LenientUri): F[Unit] def cancelJob(base: LenientUri, job: Ident): F[BasicResult] } object JoexClient { private[this] val logger = getLogger def apply[F[_]: Sync](client: Client[F]): JoexClient[F] = new JoexClient[F] { def notifyJoex(base: LenientUri): F[Unit] = { val notifyUrl = base / "api" / "v1" / "notify" val req = Request[F](Method.POST, uri(notifyUrl)) logger.fdebug(s"Notify joex at ${notifyUrl.asString}") *> client.expect[String](req).map(_ => ()) } def notifyJoexIgnoreErrors(base: LenientUri): F[Unit] = notifyJoex(base).attempt.map { case Right(()) => () case Left(ex) => logger.warn( s"Notifying Joex instance '${base.asString}' failed: ${ex.getMessage}" ) () } def cancelJob(base: LenientUri, job: Ident): F[BasicResult] = { val cancelUrl = base / "api" / "v1" / "job" / job.id / "cancel" val req = Request[F](Method.POST, uri(cancelUrl)) client.expect[BasicResult](req) } private def uri(u: LenientUri): Uri = Uri.unsafeFromString(u.asString) } def resource[F[_]: ConcurrentEffect](ec: ExecutionContext): Resource[F, JoexClient[F]] = BlazeClientBuilder[F](ec).resource.map(apply[F]) }
Example 81
Source File: RestAppImpl.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.restserver import scala.concurrent.ExecutionContext import cats.effect._ import cats.implicits._ import docspell.backend.BackendApp import docspell.common.NodeType import docspell.ftsclient.FtsClient import docspell.ftssolr.SolrFtsClient import org.http4s.client.Client final class RestAppImpl[F[_]: Sync](val config: Config, val backend: BackendApp[F]) extends RestApp[F] { def init: F[Unit] = backend.node.register(config.appId, NodeType.Restserver, config.baseUrl) def shutdown: F[Unit] = backend.node.unregister(config.appId) } object RestAppImpl { def create[F[_]: ConcurrentEffect: ContextShift]( cfg: Config, connectEC: ExecutionContext, httpClientEc: ExecutionContext, blocker: Blocker ): Resource[F, RestApp[F]] = for { backend <- BackendApp(cfg.backend, connectEC, httpClientEc, blocker)( createFtsClient[F](cfg) ) app = new RestAppImpl[F](cfg, backend) appR <- Resource.make(app.init.map(_ => app))(_.shutdown) } yield appR private def createFtsClient[F[_]: ConcurrentEffect: ContextShift]( cfg: Config )(client: Client[F]): Resource[F, FtsClient[F]] = if (cfg.fullTextSearch.enabled) SolrFtsClient(cfg.fullTextSearch.solr, client) else Resource.pure[F, FtsClient[F]](FtsClient.none[F]) }