Skip to content

Instantly share code, notes, and snippets.

@ehoner
Created July 31, 2018 01:06
Show Gist options
  • Save ehoner/de26456feecdd644ade36b7b1e60ee5a to your computer and use it in GitHub Desktop.
Save ehoner/de26456feecdd644ade36b7b1e60ee5a to your computer and use it in GitHub Desktop.
Notes and comments from HTTP design session.

HTTP design session notes and comments

This meeting focused primarily around the idea of a ServiceDefinition. From a ServiceDefintion, the HTTP API can produce a running service, documentation and a client.

John referenced previous work, redeyes, which will be our starting point.

conceptual prototype

Below is the example from the redeyes README

import redeyes.api._

val request: Api[Int] = 
  GET >~>
  path("/employees/") >~>
  contentType("application/json") >~>
  queryInt("limit")

val response: Api[Json] = 
  contentType("application/json") >~> content(JsonCodec)

val listEmployees = serviceM(request, response) { limit =>
  loadAllEmployees(limit).toJson
}

val docs: Markdown = document(listEmployees)

val server: Task[Unit] = compileToServer(listEmployees)

val remoteService: Int => Task[Json] = remotely(listEmployees)("localhost", 80)

server.run

The ServiceDefinition has the following components:

  • request[A]: A definition of an HTTP endpoint, method, URL, headers, etc. Where A is extracted from the request.
  • response[B]: The result of a request, and encoders specific to T.
  • service: Monadic function where A => M[B], such that a request provides A and the response B. (For now avoid focusing on M, the key is providing a function that accepts A and returns B).
  • documentation: Can be produced from any ServiceDefinition
  • "server": Produces a "runnable" HTTP service and a client.

John spent some time focused on going through his thinking on what is necessary to solve this problem and why other problems have failed in the past. I highly suggest reading through redeyes and the README is a great place to start.

Key Takeaways

Balance is crucial to this effort. Previous efforts with Parsers and Functions were unable to meet these goals. Functions and Parser both compose sufficiently well to build a ServiceDefinition but the semantics of that definition are lost and cannot be inspected. The inspection is necessary for documentation and client generation (key insight).

Preparation for Thursday

I think that John will be walking us through some more of the high level design work necessary to get the balance correct. I suspect that Applicative Functors will be very relevant to our project. These types will allow us to "inspect" any part of a ServiceDefinition and produce documentation and client in a type safe manner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment