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

Two Scoops of Scala

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

Two Scoops of Scala

April tech talk at FullContact

Avatar for Kārlis Lauva

Kārlis Lauva

April 09, 2014

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