Provides http4s request authentication using AWS Signature Version 4 signing.
The blog post A Scala Alternative to AWS SDK for Java gives an introduction.
Inspired by filosganga/http4s-aws, but with significant differences.
You can add the following lines to build.sbt to use the library.
libraryDependencies ++= Seq(
"com.magine" %% "http4s-aws" % http4sAwsVersion,
"com.magine" %% "http4s-aws-s3" % http4sAwsVersion
)Make sure to replace http4sAwsVersion with a release version.
Replace %% with %%% if you are using Scala.js.
Create a CredentialsProvider and use AwsSigningClient to wrap an existing client.
import cats.effect.IO
import cats.effect.IOApp
import com.magine.aws.Region
import com.magine.http4s.aws.AwsServiceName
import com.magine.http4s.aws.AwsSigningClient
import com.magine.http4s.aws.CredentialsProvider
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.Request
object Main extends IOApp.Simple {
def run: IO[Unit] = {
val client =
for {
client <- EmberClientBuilder.default[IO].build
provider <- CredentialsProvider.default(client)
region = Region.EU_WEST_1
serviceName = AwsServiceName.Elasticsearch
signingClient = AwsSigningClient(provider, region, serviceName)(client)
} yield signingClient
val request: Request[IO] =
Request()
client.use(_.expect[Unit](request))
}
}For chunked uploads, set Transfer-Encoding: chunked and set the X-Amz-Decoded-Content-Length header to the total length of the request body. In this case, avoid setting the Content-Length header, since it will then also have to account for the signing content length.
If pre-signing of requests is necessary, use AwsPresigning.
import cats.effect.IO
import cats.effect.IOApp
import com.magine.aws.Region
import com.magine.http4s.aws.AwsPresigning
import com.magine.http4s.aws.AwsServiceName
import com.magine.http4s.aws.CredentialsProvider
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.Request
import scala.concurrent.duration._
object Main extends IOApp.Simple {
def run: IO[Unit] = {
val presigning =
for {
client <- EmberClientBuilder.default[IO].build
provider <- CredentialsProvider.default(client)
region = Region.EU_WEST_1
serviceName = AwsServiceName.S3
expiry = 5.minutes
presigning = AwsPresigning(provider, region, serviceName, expiry)
} yield presigning
val request: Request[IO] =
Request()
presigning
.use(_.presign(request))
.map(_.uri.renderString)
.flatMap(IO.println)
}
}The http4s-aws-s3 module adds support for Amazon S3 multipart uploads.
import cats.effect.IO
import cats.effect.IOApp
import com.magine.aws.Region
import com.magine.http4s.aws.CredentialsProvider
import com.magine.http4s.aws.s3.S3MultipartUpload
import com.magine.http4s.aws.s3.syntax.*
import fs2.Stream
import fs2.text
import io.circe.Json
import org.http4s.MediaType
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.headers.`Content-Type`
object Main extends IOApp.Simple {
def run: IO[Unit] = {
val multipartUpload =
for {
client <- EmberClientBuilder.default[IO].build
provider <- CredentialsProvider.default(client)
bucket = bucket"bucket"
key = key"key"
region = Region.EU_WEST_1
multipartUpload = S3MultipartUpload(client, provider, region)
.withContentType(`Content-Type`(MediaType.application.json))
.withMaxConcurrentUploads(5)
.uploadTo(bucket, key)
} yield multipartUpload
multipartUpload.use { multipartUpload =>
Stream(Json.obj())
.map(_.noSpaces)
.through(text.utf8.encode)
.through(multipartUpload)
.compile
.onlyOrError
.flatMap(IO.println)
}
}
}