Skip to content

Inspired by Sinatra, Geryon is a library that runs on top of Netty 4, helping you build reactive HTTP services in the JVM.

License

Notifications You must be signed in to change notification settings

gabfssilva/geryon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

98 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

geryon

Inspired by Sinatra, Geryon is a library that runs on top of Netty 4, helping you build reactive HTTP services in the JVM.

Using in your project

Importing the library using Gradle

repositories {
    maven {
        url  "https://dl.bintray.com/geryon/releases"
    }
}

dependencies {
    compile "org.geryon:geryon:0.0.4"
}

If you are using Scala and SBT

 libraryDependencies +=
  "org.geryon" %% "geryon-scala" % "0.0.4"

Tutorial

For now on, every single available feature of Geryon will be showed over here. Since Geryon was developed just to be an HTTP layer for your application, not a fullstack framework, there's not much for you to learn.

The obligatory Hello World

Java

//this import does all the trick
import static org.geryon.Http.*;

public class Sample {
    public static void main(String[] args) {
        get("/hello", request -> supply(() -> "Hello, " + request.queryParameters().get("name")));
    }
}

Kotlin

//this import does all the trick
import org.geryon.Http.*

fun main(args: Array<String>) {
    get("/hello") { supply { "hello, ${it.queryParameters()["name"]}" } }
}

Scala

//this import does all the trick
import org.geryon.scaladsl._

object Sample extends App {
  get("/hello") { implicit request => supply { s"hello, ${param("name")}}" } }
}

Your app will be running at 8080.

More examples in:

Simple Server in Java ~ Simple Server in Kotlin ~ Simple Server in Scala

Understanding HTTP handlers

Available methods

For now, these are all the http methods available:

get
post
put
delete
patch
options
head
trace
connect

Basic usage of a handler

Java

get("/path", request -> futureResponse)

Kotlin

get("/path") { request -> futureResponse }

Scala

get("/path") { implicit request => futureResponse }

Handler with matcher

Geryon offers a simple matcher for you implement your own validation, thus you can validate, based on the request, if the handler is the right one.

Java

get("/path", request -> boolean, request -> futureResponse)

Kotlin

get("/path", request -> boolean) { request -> futureResponse }

Scala

get("/path", request => boolean) { request => futureResponse }

Working with path parameters

Java

get("/path/:myParameter", request -> {
   final String myParameter = request.pathParameters().get("myParameter");
   //do whatever you want to do over here
   return futureResponse;
})

Kotlin

get("/path/:myParameter") { //in Kotlin, you can also omit the parameter if a function has only one parameter
   //you can use the parameter using the keyword "it"
   val myParameter = it.pathParameters()["myParameter"]
   //do whatever you want to do over here
   futureResponse
}

Scala

get("/path/:myParameter") { implicit request =>
   val myParameter = pathParameter("myParameter") //or just param("myParameter")
   //do whatever you want to do over here
   futureResponse
}

Working with query parameters

Java

get("/path", request -> {
   final String myParameter = request.queryParameters().get("myParameter");
   //do whatever you want to do over here
   return futureResponse;
})

Kotlin

get("/path") { //in Kotlin, you can also omit the parameter if a function has only one parameter
   //you can use the parameter using the keyword "it"
   val myParameter = it.queryParameters()["myParameter"]
   //do whatever you want to do over here
   futureResponse
}

Scala

get("/path") { implicit request =>
   val myParameter = queryParameter("myParameter") //or just param("myParameter")
   //do whatever you want to do over here
   futureResponse
}

Working with matrix parameters

Java

get("/path", request -> {
   final String myParameter = request.matrixParameters().get("path").get("myParameter");
   //do whatever you want to do over here
   return futureResponse;
})

Kotlin

get("/path") { //in Kotlin, you can also omit the parameter if a function has only one parameter
   //you can use the parameter using the keyword "it"
   val myParameter = it.matrixParameters()["path"]!!["myParameter"]
   //do whatever you want to do over here
   futureResponse
}

Scala

get("/path") { implicit request =>
   val myParameter = matrixParameter("path" -> "matrixParameter")
   
   //if you have more than one matrix parameter per path, you can do this:
   //val (myParam1, myParam2) = matrixParameter("path" -> ("myParam1", "myParam2"))
   
   //do whatever you want to do over here
   futureResponse
}

Working with headers

Java

get("/path", request -> {
   final String myParameter = request.headers().get("myParameter");
   //do whatever you want to do over here
   return futureResponse;
})

Kotlin

get("/path") { //in Kotlin, you can also omit the parameter if a function has only one parameter
   //you can use the parameter using the keyword "it"
   val myParameter = it.headers()["myParameter"]
   //do whatever you want to do over here
   futureResponse
}

Scala

get("/path") { implicit request =>
   val myParameter = header("myParameter")
   //do whatever you want to do over here
   futureResponse
}

Working with the request body

Java

post("/path", request -> {
   final String body = request.body();
   //do whatever you want to do over here
   return futureResponse;
})

Kotlin

post("/path") { //in Kotlin, you can also omit the parameter if a function has only one parameter
   //you can use the parameter using the keyword "it"
   val body = it.body()
   //do whatever you want to do over here
   futureResponse
}

Scala

post("/path") { implicit request =>
   val requestBody = body
   //do whatever you want to do over here
   futureResponse
}

Understanding the models (Request and Response)

Request

Basically, a Request contains the following fields:

url: String
rawPath: String
body: String
contentType: String
method: String
headers: Map[String, String]
queryParameters: Map[String, String]
pathParameters: Map[String, String]
matrixParameters: Map[String, Map[String, String]]

ScalaDslRequest and the inherited request methods

In Scala, you can use a series of methods which takes an implicit request to avoid boilerplate code:

val pathParam = pathParam("pathParam")
val queryParam = queryParam("queryParam")
val pathOrQueryParam = param("param") //this method tries to get the path parameter with the informed key, if there is none, tries to get a query parameter
val header = header("header")
val (matrixParam1, matrixParam2) = matrixParameter("path" -> ("matrixParam1", "matrixParam2"))
val requestBody = body
val requestUrl = url
val requestContentType = contentType

Response

body: String
httpStatus: Int
headers: Map[String, String]
contentType: String

Response Builder

You always create a response using a response builder. In Java, Kotlin or Scala, there's already a method called "response", which is a response builder that helps you build your response

Java or Kotlin

response()
   .body("this is the response body")
   .httpStatus(201)
   .header("headerName", "headerValue")
   .header("headerName2", "headerValue2")
   .contentType("text/plain")
   .build();

Scala

response
   .body("this is the response body")
   .httpStatus(201)
   .header("headerName" -> "headerValue")
   .header("headerName2" -> "headerValue2")
   .contentType("text/plain")
   .build()

Predefined responses

There are a bunch of predefined responses already created to help you return your response in a very easy way:

Java or Kotlin

ok();
ok("response body");

created("https://location");
created("https://location", "response body");

noContent();

accepted();
accepted("response body");

notFound();
notFound("response body");

conflict();
conflict("response body");

unauthorized();
unauthorized("response body");

internalServerError();
internalServerError("response body");

Scala

ok
ok("response body")

created("https://location")
created("https://location", "response body")

noContent

accepted
accepted("response body")

notFound
notFound("response body")

conflict
conflict("response body")

unauthorized
unauthorized("response body")

internalServerError
internalServerError("response body")

Of course, if you feel like we could add other predefined response, feel free to ask or to pull request. ;)

Geryon configurations

Changing the http port

Java, Kotlin or Scala

port(9090);

Using a default content type

Java, Kotlin or Scala

defaultContentType("application/json");

Changing the event loop thread number

Java, Kotlin or Scala

eventLoopThreadNumber(2);

Adding a default response header

Java or Kotlin

defaultHeader("X-Powered-By", "geryon");

Scala

defaultHeader("X-Powered-By" -> "geryon")

Adding an exception handler

Java

handlerFor(Exception.class, (e, r) -> internalServerError(String.format("ups, you called %s and it seems that an exception occurred: %s", r.url(), e.getMessage())));

Kotlin

handlerFor(Exception::class.java) { exception, request ->
  internalServerError("ups, you called ${request.url()} and it seems that an exception occurred: ${exception.message}")
}

Scala

handlerFor[RuntimeException] { implicit request => exception =>
  internalServerError(s"ups, you called $url and it seems that an exception occurred: ${exception.getMessage}")
}

How to contribute

//TODO