finagle / finch Goto Github PK
View Code? Open in Web Editor NEWScala combinator library for building Finagle HTTP services
Home Page: https://finagle.github.io/finch
License: Apache License 2.0
Scala combinator library for building Finagle HTTP services
Home Page: https://finagle.github.io/finch
License: Apache License 2.0
Probably based on standard CHM.
It may looks like a finagled filter that a) checks the local cache and then b) performs request handling:
object User extends Endpoint {
def route {
case Method.GET -> Root / "users" => RetrieveFromCache("all-users") andThen GetAllUsers
}
}
It's better to keep the number of builing blocks as small as possible. It looks like we realy don't need a special Facet
entity - we can use either pure Filter
-s of pure Service
-s for this.
The goal is to keep the API unchanged.
Endpoint {
def serveAt(port)(fn): Server
def exposeWith(fn): Service[HttpRequest, HttpResponse]
}
implicit def prepareEndpoint(respond: Endpoint[HttpRequest, JsonResponse]): Endpoint[HttpRequest, HttpResponse] = {
respond afteThat TurnJsonIntoHttp
}
Http.serve(":8081", endpoint.toService)
Finch 0.0.1
pacakge.scala
(I have to put everything insinde a single file)HtttService
and type-parametrized HttpServiceOf[A]
Resource
that exposes a route
and might be composed with either orElse
or andThen
Facet
that converts service's responsesafterThat
methodJsonArray
and JsonObject
TrunJsonToHttp
and WrapJsonWithMetaAsTag
RestApi
runnable-class with exposeAt(port)
methodThis should take 100-200 SLOC.
for {
e <- RequiredParam("email")
p <- RequiredParam("password")
_ <- "password" shouldNot "be empty" when { p.nonEmpty }
_ <- "password" should "be longer then 10 symbols" when { p.length > 10 }
} yield (e, p)
RequiredParam
should only do that. Both OptionalParam
and Param
should return None
instead.
JsonArray
might contains only JsonResponse
elements.
It might be called a Sink
.
trait Sink[-ReqIn, +ReqOut] {
def afterThat(next: Sink[]): Sink
def afterThat(service: Service): Service
def afterThat(resource: RestResource): RestResourse
}
The usage looks as follows:
val b = a afterThat service
It should be as short as possible.
Something like this:
val credentials: ParamFetcher[(String, String)] = for {
name <- Fetch("name", "*".r)
password <- Fetch("password", "*".r)
} yield (name, password)
val f: Future[(String, String)] = credentials(request) handle {
case e: ParamFetchError =>
// e.wrongParams: Map[String, String]
// Map("name" -> "No param.", "password" -> "Does not match.")
("1", "2") // default values
}
Like this:
val i1 = RequiredIntParam("d")
val l1 = RequiredLongParam("l")
val i2 = OptionalIntParam("d")
val l2 = OptionalLongParam("d")
scala.util.parsing.json
is deprecated in 2.11, and there are lots of better JSON ASTs and serializers around these days. Would you be interested in a pull request that makes the JSON library pluggable?
I don't like how the default JSONType is formatted. We don't need to escape the forward slashes.
val credentials = for {
n <- RequiredParam("name")
p <- RequiredParam("pass")
} yield (n, p)
val validator = for {
n <- Validator(...) // name validator
p <- Validator(...) // password validator
} yield (n, p)
for {
(name, pass) <- credentials(req)
_ <- validator(name, pass)
}
JsonPath("a.b.c.d" -> 10) =
JsonObject(
"a" -> JsonObject(
"b" -> JsonObject(
"c" -> JsonOnject(
"d" -> 10
))))
Finch should be able to resolve loopback request w/o a network stack. This might be implemented as a function in RestApi
class that delivers the requests to a backend service directly:
object Api extends RestApi {
def port = 8080
def resource = A orElse B orElse C
Await.ready(this)
}
I should create an http://repo.konfettin.ru repo for our private libraries.
This should increase the readability.
All JSON primitives/functions should be tests. As well as base API.
RestResource
is Endpoint
RestApi
is just Api
I should review all the scala-doc in finch.io.
The default TurnJsonIntoHttp
should use a default formatter. However, users should be able to pass their own formatters into a facet. The API shoudn't change.
Sometimes it make sense to use a Scala type-checker in order to write a type-safe filters within a custom request-type. The most popular example - having an AuthorizedHttpRequest
instead of HttpRequest
. Users should be able to do that with Finch.
def a: RequestReader[Option[Unit]] = NoParams
def b: FutureRequestReader[Unit] = NoRequiredParams
def c: FutureRequestReader[Option[Unit]] = NoOptionalParams
JsonArray of unique items.
Something like:
val rep = Ok()
val rep = BadRequest()
val rep = Forbidden()
val rep = Created()
val rep = Unauthorized()
val rep = InternalServerError()
http://www.playframework.com/documentation/2.0/api/scala/play/api/mvc/Results.html
val rep = Ok(JsonObject("a" - > 10))
There should a way to hide all the implicit classes from users. The comminon sense: they shouldn't be listed in IDE autocoplition on io.finch.
expression but still should alter the requered values with new methods. I'm not shure whether this possible or not.
I would use the same LICENSE as Finagle essentially, Apache Public License 2.0 :)
It looks crazy. I need a json-reader-monad to fight this:
val feedbacksWithAttachments = feedbacks flatMap { seq =>
Future.collect(seq.map { o =>
val id = o.get[Int]("id")
o.flatMapTagInFuture[JSONObject]("feedback") { f =>
f.flatMapTagInFuture[JSONArray]("attachments") { _ =>
for {
query <- client.prepare("select a.id, a.sent, a.path, a.description from attachments a join " +
"feedback_attachments fa on a.id=fa.fid_attachment join feedbacks f on " +
"f.id=fa.fid_feedback where f.id=$1 limit $2")
rep <- query.select(id, Config[Int]("api.innerArraySizeLimit")) { row =>
JsonObject(
"id" -> row.get[Int]("id"),
"uri" -> row.get[String]("path"),
"sent" -> Gmt(row.get[Timestamp]("sent")),
"description" -> row.get[String]("description")
)
}
} yield JsonArray(rep)
}
}
})
}
I should thing about implementing this code as JsonObject
function:
val rep: Seq[JSONObject] = ???
val grouped = rep.groupBy { _.get[Int]("id") }
grouped.foldLeft(Seq.empty[JSONObject]) { case (acc, (_, seq)) =>
val joinedJson = seq.foldLeft(JsonObject("feedback.attachments" -> JsonArray.empty)) {
JsonObject.joinRight("feedback.attachments")
}
acc ++ Seq(joinedJson)
}
A bunch of new methods should be implemented in RestApiOf
:
def apply(req: HttpRequest)
def apply(uri: String)
The default behaviour for now is to ignore null values. We should provide an alternative way and decide what should be a default strategy.
Probably the default strategy should be to keep null-values. But an alternative way is to skip them:
JsonObject.compact(...)
The JsonNull
object from the commit 7755def should be restored.
It also would be nice to having a way of compatiing json object (removing null values). Like this:
val json = JsonObject("")
val c = json.compact
I can't stop to use monads everywhere. Sorry.
val doAllTheMagic = for {
http <- TurnJsonIntoHttp
httpWithHeaders <- AddHeaders("asd", "asd")
} yield httpWithHeaders
service afterThat allTheMagic
I have to decribe the Finagle-Json integration provided by Finch.io in a Readme file.
To use in this way:
val reader = for {
a <- RequiredHeader("a")
b <- RequiredParam("b")
} yield (a, b)
Like this:
val a = JsonObject()
val b = a("sent") map { any => any }
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.