Skip to content

About

Signed AWS API requests for http4s 🔒

Topics

Resources

Stars

8 stars

Watchers

3 watching

Forks

Repository files navigation

🔒 http4s-aws

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.

Usage

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 or Scala Native.

Signing

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))
  }
}

Chunking

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.

Pre-signing

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)
  }
}

S3

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)
    }
  }
}

License

Copyright 2025 Magine Pro
Copyright 2026 Viktor Rudebeck

Licensed under the Apache License, Version 2.0.
Created by Viktor Rudebeck at Magine Pro and independently maintained since 2026.

About

Signed AWS API requests for http4s 🔒

Topics

Resources

Stars

8 stars

Watchers

3 watching

Forks

Releases

Used by

Contributors

Languages