Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Two Scoops of Scala

Two Scoops of Scala

April tech talk at FullContact

Kārlis Lauva

April 09, 2014
Tweet

More Decks by Kārlis Lauva

Other Decks in Programming

Transcript

  1. Unfiltered? • A toolkit for HTTP in Scala • Really,

    really modular • Works with Netty and Jetty • Built for meetup.com realtime API • Makes good use of Scala's idioms
  2. Toolchain • SBT - Scala Build Tool • Best conventions

    from Maven world • Iterative development in SBT shell
  3. My setup • IntelliJ + SBT console(s) inside tmux •

    IntelliJ 13 has SBT support baked in
  4. Deployment • Works great with Jenkins & Asgard • Minimal

    configuration tweaks needed (wait for the next slide)
  5. • A tool for fetching templates for Scala projects •

    g8 skazhy/unfiltered-netty-rx • All SBT plugins for deployment and IntelliJ are included Bootstrapping with giter8
  6. object MyPlan extends cycle.Plan with cycle.ThreadPool with ServerErrorResponse { def

    intent = { case GET(Path("/")) => ResponseString("Hello!") case OPTIONS(_) => Created ~> Location("/foo") case _ => NotFound } } unfiltered.netty.Http(1337).handler(MyPlan).run()
  7. Pattern matching • Decomposing data structures to extract certain fields

    or validate them • Really powerful in Scala • “routing” mechanism in Unfiltered
  8. Match on request methods • Use builtins: GET(_) POST(_) PATCH(_)

    • Or define your own: object SPACEJUMP extends Method("SPACEJUMP")
  9. What happens under the hood? class Method(method: String) { def

    unapply[T](req: HttpRequest[T]) = if (req.method.equalsIgnoreCase(method)) Some(req) else None } object POST extends Method("POST")
  10. ...or query parameters object AccountIdParam extends Params.Extract("numericId", Params.first ~> Params.nonempty

    ~> Params.long) PATCH(Params(AccountIdParam(accountId))) // Will extract 1234 from PATCH /foo?numericId=1234
  11. Responses are composable case _ => Unauthorized ~> ResponseString("No pasaran")

    ~> ResponseHeader("WWW-Authenticate", "Basic realm=foo")
  12. Async made easy case req @ GET(Path("/async")) => val futureOp

    = asyncOperation futureOp.onSuccess { case result => req.respond(Ok ~> ResponseString(result)) } futureOp.onFailure { case _ => req.respond(InternalServerError) }
  13. • Separate library for testing with Specs2 • Mocking with

    Mockito • Comes bundled with the giter8 template unfiltered-specs2
  14. object OperationPostSpec extends Specification { "PATCH /foo" should { lazy

    val r = Http(url((host \ "foo").PATCH)) lazy val response = r() "return HTTP 200" in { response.getResponseStatus mustEqual 200 } } }
  15. Consider using Unfiltered when you... • need an async &

    lightweight HTTP service • Have separate business logic • Want to leverage the λ-force