Skip to content
Permalink
Browse files

Initial commit

  • Loading branch information...
amrhassan committed Dec 3, 2017
0 parents commit 4e4e5dc38c376caeb8510869d0d8ccd1801fe1ea
@@ -0,0 +1,2 @@
.idea
target
@@ -0,0 +1,21 @@

name := "aws4s"
organization := "org.aws4s"
scalaVersion := "2.12.4"
version := "0.1.0-SNAPSHOT"

scalacOptions ++= Seq(
"-Ypartial-unification"
)

resolvers += Resolver.jcenterRepo

val http4sVersion = "0.18.0-M4"
val awsSignerVersion = "0.5.1"

libraryDependencies ++= Seq(
"org.http4s" %% "http4s-dsl" % http4sVersion,
"org.http4s" %% "http4s-blaze-client" % http4sVersion,
"org.http4s" %% "http4s-scala-xml" % http4sVersion,
"io.ticofab" %% "aws-request-signer" % awsSignerVersion,
)
@@ -0,0 +1 @@
sbt.version=1.0.4
@@ -0,0 +1,12 @@
package org.aws4s

import cats.Show
import cats.implicits._

abstract class Failure(message: String) extends RuntimeException(message) {
override def toString: String = this.show
}

object Failure {
implicit val showFailure: Show[Failure] = Show.show(err => s"aws4s failure: ${err.getMessage}")
}
@@ -0,0 +1,3 @@
package org.aws4s

case class Region(name: String) extends AnyVal
@@ -0,0 +1,7 @@
package org.aws4s

case class Service(name: String) extends AnyVal

object Service {
val Sqs = Service("sqs")
}
@@ -0,0 +1,46 @@
package org.aws4s

import java.time.{LocalDateTime, ZoneId}
import cats.effect.Sync
import cats.implicits._
import com.amazonaws.auth.AWSCredentialsProvider
import org.http4s.{Header, Headers, Method, Request, Uri}

private [aws4s] object Signing {

def signed[F[_] : Sync](credentials: AWSCredentialsProvider, region: Region)(req: Request[F]): F[Request[F]] = {

val extraHeaders: F[Headers] =
req.body.runLog map {
case body if body.isEmpty => signedHeaders(credentials, region, Service.Sqs)(req.uri.path, req.method, req.params, req.headers, None)
case body => signedHeaders(credentials, region, Service.Sqs)(req.uri.path, req.method, req.params, req.headers, Some(body.toArray))
}

extraHeaders map { hs =>
req.withHeaders(hs)
}
}

private def signedHeaders(
credentials: AWSCredentialsProvider,
region: Region,
service: Service
)(path: Uri.Path,
method: Method,
queryParams: Map[String, String],
headers: Headers,
body: Option[Array[Byte]]): Headers = {

val clock = () => LocalDateTime.now(ZoneId.of("UTC"))
val signer = io.ticofab.AwsSigner(credentials, region.name, service.name, clock)

Headers(
signer.getSignedHeaders(
path,
method.name,
queryParams,
headers.toList.map(h => (h.name.value, h.value)).toMap, body
).toList.map({ case (k, v) => Header(k, v).parsed })
)
}
}
@@ -0,0 +1,8 @@
package org.aws4s.sqs

sealed abstract class Failure(message: String) extends org.aws4s.Failure(message)
case class MalformedQueueUri(message: String) extends Failure(s"Malformed SQS Queue URI: $message")

object Failure {
def malformedSqsQueueUri(message: String): Failure = MalformedQueueUri(message)
}
@@ -0,0 +1,26 @@
package org.aws4s.sqs

import cats.implicits._
import org.aws4s.Region
import org.http4s.Uri

case class Queue private(uri: Uri, host: String, region: Region)

object Queue {

def fromString(uriS: String): Either[Failure, Queue] = {
Uri.fromString(uriS)
.leftMap(err => MalformedQueueUri(err.message) : Failure)
.flatMap { uri =>
uri.host match {
case Some(host) =>
host.value.split('.').drop(1).headOption match {
case Some(region) => Either.right(Queue(uri, host.value, Region(region)))
case None => Either.left(Failure.malformedSqsQueueUri("No region present in the queue URI"))
}
case None =>
Either.left(Failure.malformedSqsQueueUri("Missing host in the queue URI"))
}
}
}
}
@@ -0,0 +1,22 @@
package org.aws4s.sqs

import cats.Monad
import cats.effect.Sync
import cats.implicits._
import com.amazonaws.auth.AWSCredentialsProvider
import org.aws4s.Signing
import org.http4s.headers.Host
import org.http4s.{Headers, Method, Request, UrlForm}

private object Requests {

def sendMessage[F[_] : Monad : Sync](q: Queue, message: String, credentialsProvider: AWSCredentialsProvider): F[Request[F]] = {
val body = UrlForm(
"Action" -> "SendMessage",
"MessageBody" -> message
)
Request[F](Method.POST, q.uri, headers = Headers(Host(q.host, None)))
.withBody[UrlForm](body)
.flatMap(Signing.signed(credentialsProvider, q.region))
}
}
@@ -0,0 +1,20 @@
package org.aws4s.sqs

import cats.effect.Sync
import com.amazonaws.auth.AWSCredentialsProvider
import org.http4s.client.Client
import org.http4s.scalaxml._

class Sqs[F[_] : Sync](client: Client[F], aWSCredentialsProvider: AWSCredentialsProvider) {

def sendMessage(q: Queue, message: String): F[scala.xml.Elem] = {
val request = Requests.sendMessage(q, message, aWSCredentialsProvider)
client.fetchAs(request)
}
}

object Sqs {

def apply[F[_]: Sync](client: Client[F], aWSCredentialsProvider: AWSCredentialsProvider): Sqs[F] =
new Sqs(client, aWSCredentialsProvider)
}

0 comments on commit 4e4e5dc

Please sign in to comment.
You can’t perform that action at this time.