Skip to content

Commit ec4de8b

Browse files
committed
Refactor to be generic to the server type
1 parent e62325b commit ec4de8b

File tree

14 files changed

+204
-235
lines changed

14 files changed

+204
-235
lines changed

.scalafmt.conf

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,3 @@ rewrite.rules = [RedundantBraces, SortImports, PreferCurlyFors]
2121

2222
docstrings = JavaDoc
2323
importSelectors = singleLine
24-
25-
newlines.alwaysBeforeTopLevelStatements = true

build.sbt

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
11
lazy val commonSettings = Seq(
22
organization := "io.github.howardjohn",
3-
scalaVersion := "2.12.4"
3+
scalaVersion := "2.12.6"
44
)
55

6-
lazy val core = project
6+
lazy val root = project
7+
.in(file("."))
8+
.settings(commonSettings)
9+
.settings(noPublishSettings)
10+
.aggregate(http4s, exampleHttp4s)
11+
12+
lazy val CirceVersion = "0.9.0"
13+
lazy val ScalaTestVersion = "3.0.4"
14+
15+
lazy val common = project
16+
.in(file("common"))
17+
.settings(commonSettings)
18+
.settings(noPublishSettings)
19+
.settings(
20+
moduleName := "common",
21+
libraryDependencies ++=
22+
Seq(
23+
"io.circe" %% "circe-generic" % CirceVersion,
24+
"io.circe" %% "circe-parser" % CirceVersion,
25+
"org.scalatest" %% "scalatest" % ScalaTestVersion % "test"
26+
)
27+
)
28+
29+
lazy val http4s = project
730
.in(file("http4s-lambda"))
831
.settings(publishSettings)
932
.settings(commonSettings)
@@ -13,37 +36,31 @@ lazy val core = project
1336
moduleName := "http4s-lambda",
1437
scalacOptions ++= Seq("-Ypartial-unification"),
1538
libraryDependencies ++= {
16-
val Http4sVersion = "0.18.0-M8"
17-
val CirceVersion = "0.9.0"
39+
val Http4sVersion = "0.18.10"
1840
Seq(
1941
"org.http4s" %% "http4s-core" % Http4sVersion,
2042
"org.http4s" %% "http4s-circe" % Http4sVersion,
2143
"io.circe" %% "circe-parser" % CirceVersion,
2244
"io.circe" %% "circe-generic" % CirceVersion,
23-
"org.scalatest" %% "scalatest" % "3.0.4" % "test",
45+
"org.scalatest" %% "scalatest" % ScalaTestVersion % "test",
2446
"org.http4s" %% "http4s-dsl" % Http4sVersion % "test"
2547
)
2648
}
2749
)
50+
.dependsOn(common)
2851

29-
lazy val example = project
30-
.in(file("example"))
52+
lazy val exampleHttp4s = project
53+
.in(file("example-http4s"))
3154
.settings(noPublishSettings)
3255
.settings(commonSettings)
3356
.settings(
34-
moduleName := "example",
35-
assemblyJarName in assembly := "example.jar",
57+
moduleName := "example-http4s",
58+
assemblyJarName in assembly := "example-http4s.jar",
3659
libraryDependencies ++= Seq(
3760
"org.http4s" %% "http4s-dsl" % "0.18.0-M8"
3861
)
3962
)
40-
.dependsOn(core)
41-
42-
lazy val root = project
43-
.in(file("."))
44-
.settings(commonSettings)
45-
.settings(noPublishSettings)
46-
.aggregate(core, example)
63+
.dependsOn(http4s)
4764

4865
lazy val noPublishSettings = Seq(
4966
publish := {},
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.github.howardjohn.lambda
2+
3+
import io.circe
4+
import io.circe.generic.auto._
5+
import io.circe.parser.decode
6+
import io.circe.syntax._
7+
8+
object Encoding {
9+
case class ProxyRequest(
10+
httpMethod: String,
11+
path: String,
12+
headers: Option[Map[String, String]],
13+
body: Option[String],
14+
queryStringParameters: Option[Map[String, String]]
15+
)
16+
17+
case class ProxyResponse(
18+
statusCode: Int,
19+
headers: Map[String, String],
20+
body: String
21+
)
22+
23+
def parseRequest(rawInput: String): Either[circe.Error, ProxyRequest] = decode[ProxyRequest](rawInput)
24+
25+
def encodeResponse(response: ProxyResponse): String =
26+
response.asJson.noSpaces
27+
28+
def reconstructPath(request: ProxyRequest): String = {
29+
val requestString = request.queryStringParameters
30+
.map {
31+
_.map {
32+
case (k, v) => s"$k=$v"
33+
}.mkString("&")
34+
}
35+
.map { qs =>
36+
if (qs.isEmpty) "" else "?" + qs
37+
}
38+
.getOrElse("")
39+
request.path + requestString
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
1-
package io.github.howardjohn.http4s.lambda
1+
package io.github.howardjohn.lambda
22

33
import java.io.{InputStream, OutputStream}
44
import java.nio.charset.StandardCharsets
55

6-
import cats.effect.IO
7-
86
import scala.io.Source
97

10-
object IOStreamOps {
8+
object StreamOps {
119
implicit class InputStreamOps(val is: InputStream) extends AnyVal {
12-
13-
def consume(): IO[String] = IO {
10+
def consume(): String = {
1411
val contents = Source.fromInputStream(is).mkString
1512
is.close()
1613
contents
1714
}
18-
1915
}
2016

2117
implicit class OutputStreamOps(val os: OutputStream) extends AnyVal {
22-
23-
def writeAndClose(contents: String): IO[Unit] = IO {
18+
def writeAndClose(contents: String): Unit = {
2419
os.write(contents.getBytes(StandardCharsets.UTF_8))
2520
os.close()
2621
}
27-
2822
}
2923
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.github.howardjohn.lambda
2+
3+
import java.io.{InputStream, OutputStream}
4+
5+
import io.github.howardjohn.lambda.Encoding._
6+
import io.github.howardjohn.lambda.StreamOps._
7+
8+
trait LambdaHandler {
9+
def handleRequest(request: ProxyRequest): ProxyResponse
10+
11+
def handle(is: InputStream, os: OutputStream): Unit = {
12+
val rawInput = is.consume()
13+
val request = parseRequest(rawInput).fold(
14+
e => throw e,
15+
identity
16+
)
17+
val rawResponse = handleRequest(request)
18+
val response = encodeResponse(rawResponse)
19+
os.writeAndClose(response)
20+
}
21+
}

example-http4s/serverless.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
service: example-http4s
2+
3+
provider:
4+
name: aws
5+
runtime: java8
6+
region: us-west-2
7+
stage: dev
8+
9+
package:
10+
artifact: target/scala-2.12/example-http4s.jar
11+
12+
functions:
13+
api:
14+
handler: io.github.howardjohn.lambda.http4s.example.Route$EntryPoint::handle
15+
events:
16+
- http:
17+
path: "{proxy+}"
18+
method: any
19+
cors: true
20+
# Uncomment below to keep the application warm
21+
# - schedule:
22+
# rate: rate(4 minutes)
23+
# input:
24+
# httpMethod: GET
25+
# path: /hello/keepWarm

example/src/main/scala/io/github/howardjohn/http4s/lambda/example/Route.scala renamed to example-http4s/src/main/scala/io/github/howardjohn/lambda/http4s/example/Route.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
package io.github.howardjohn.http4s.lambda.example
1+
package io.github.howardjohn.lambda.http4s.example
22

33
import cats.effect.IO
4+
import io.github.howardjohn.lambda.http4s.Http4sLambdaHandler
5+
import org.http4s.HttpService
6+
import org.http4s.circe.jsonOf
47
import io.circe.generic.auto._
5-
import io.github.howardjohn.http4s.lambda.LambdaHandler
6-
import org.http4s._
7-
import org.http4s.circe._
88
import org.http4s.dsl.io._
99

1010
object Route {
11-
implicit val InputDecoder = jsonOf[IO, Input]
11+
implicit val inputDecoder = jsonOf[IO, Input]
1212

1313
// Set up the route
1414
val service: HttpService[IO] = HttpService[IO] {
@@ -23,7 +23,7 @@ object Route {
2323

2424
// Define the entry point for Lambda
2525
// Referenced as ` io.github.howardjohn.http4s.lambda.example$Route::handler` in Lambda
26-
class EntryPoint extends LambdaHandler(service)
26+
class EntryPoint extends Http4sLambdaHandler(service)
2727

2828
case class Input(
2929
name: String,

example/serverless.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

http4s-lambda/src/main/scala/io/github/howardjohn/http4s/lambda/Encoding.scala

Lines changed: 0 additions & 69 deletions
This file was deleted.

http4s-lambda/src/main/scala/io/github/howardjohn/http4s/lambda/LambdaHandler.scala

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)