Git Product home page Git Product logo

scala-server-lambda's Introduction

Scala Servers for Lambda

Scala Servers for Lambda allows you to run existing Scala servers over API Gateway and AWS Lambda.

Benefits:

  • Define logic once, and use it in both a server and serverless environment.
  • Simpler testing, as the logic has been isolated from Lambda completely.
  • No need to deal with Lambda's API directly, which aren't easy to use from Scala.
  • All code is deployed to single Lambda function, meaning our functions will be kept warm more often.

Supported Servers

Dependencies

Having a large JAR can increase cold start times, so dependencies have been kept to a minimum. All servers depend on circe. Additionally:

  • http4s depends on http4s-core.
  • akka-http depends on akka-http and akka-stream.

Neither of these depend on the AWS SDK at all, which substantially reduces the size.

Getting Started

More thorough examples can be found in the examples directory.

http4s

First, add the dependency:

libraryDependencies += "io.github.howardjohn" %% "http4s-lambda" % "0.3.1"

Next, we define a simple HttpService. Then, we simply need to define a new class for Lambda.

object Route {
  // Set up the route
  val service: HttpService[IO] = HttpService[IO] {
    case GET -> Root / "hello" / name => Ok(s"Hello, $name!")
  }

  // Define the entry point for Lambda
  class EntryPoint extends Http4sLambdaHandler(service)
}

Thats it! Make sure any dependencies are initialized in the Route object so they are computed only once.

akka-http

First, add the dependency:

libraryDependencies += "io.github.howardjohn" %% "akka-http-lambda" % "0.3.1"

Next, we define a simple Route. Then, we simply need to define a new class for Lambda.

object Route {
  // Set up the route
  val route: Route =
    path("hello" / Segment) { name: String =>
      get {
        complete(s"Hello, $name!")
      }
    }

  // Set up dependencies
  implicit val system: ActorSystem = ActorSystem("example")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = scala.concurrent.ExecutionContext.Implicits.global

  // Define the entry point for Lambda
  class EntryPoint extends AkkaHttpLambdaHandler(route)
}

Thats it! Make sure any dependencies are initialized in the Route object so they are computed only once.

Deploying to AWS

To deploy to Lambda, we need to create a jar with all of our dependencies. The easiest way to do this is using sbt-assembly.

Once we have the jar, all we need to do is upload it to Lambda. The preferred way to do this is using the serverless framework which greatly simplifies this (and is what is used in the examples), but there is no issues with doing it manually.

When deploying to Lambda, the handler should be specified as <PACKAGE_NAME>.Route$EntryPoint::handle (if you followed the example above).

Finally, an API can be created in API Gateway. Lambda Proxy integration must be enabled.

Versions

Version http4s Version akka-http Version
0.4 0.20 10.1
0.3.1 0.18 10.1

scala-server-lambda's People

Contributors

2chilled avatar frj avatar howardjohn avatar jisantuc avatar kellydavid avatar rpiaggio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

scala-server-lambda's Issues

Json parsing error

Hi,

I am trying to use the library to frontend a http4s server via lambda. I am testing my application using sam local. When I am trying to invoke the application. I am get the following parsing exception. I do not know if the issue is mainly due to sam local.

java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: java.io.UncheckedIOException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class io.github.howardjohn.lambda.ProxyEncoding$ProxyRequest]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: lambdainternal.util.NativeMemoryAsInputStream@df27fae; line: 1, column: 2]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class io.github.howardjohn.lambda.ProxyEncoding$ProxyRequest]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: lambdainternal.util.NativeMemoryAsInputStream@df27fae; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1511)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1102)

Scala 2.13 version

Would it be possible to have a new version compatible with Scala 2.13?

Loss of content type

First of all, nice work.

I spotted an issue with the loss of the Content Type within the AkkaHttpLambdaHandler.proxyToAkkaRequest method.

What happens.

  1. User makes a request with Content-Type set to 'application/json' (can be anything really).
  2. Code recreates the HttpRequest by using HttpEntity.apply on the body.
  3. The above step results in the below, which can show the loss of the content-type.

HttpEntity.Strict(text/plain; charset=UTF-8,{
"name": "ArmandoPadilla"
})

From the Akka-http perspective. This causes issues when using entity[as[JsValue]] which results in.

The request's Content-Type is not supported. Expected:
application/json

Snapshot builds

Are there snapshot builds available for this project? It would be nice to have access to a snapshot for each merge to the github repo if possible.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.