A web framework written in Ceylon, which allows:
- routing GET/POST requests to simple
(Request, Response)
handlers - creating annotated controllers containing more powerful handlers
- serving static assets (HTML, CSS, JS, ...) from a directory
gyokuro is based on the Ceylon SDK,
and uses ceylon.net
's server API.
Create a new Ceylon module:
module gyokuro.demo.rest "1.0.0" {
import net.gyokuro.core "0.2";
import ceylon.net "1.3.1";
}
Add a runnable top level function that bootstraps a gyokuro application:
import net.gyokuro.core {
Application,
get,
post,
serve
}
"Run an HTTP server listening on port 8080, that will react to requests on /hello.
Static assets will be served from the `assets` directory."
shared void run() {
// React to GET/POST requests using a basic handler
get("/hello", void (Request request, Response response) {
response.writeString("Hello yourself!");
});
// Shorter syntax that lets Ceylon infer types and lets gyokuro
// write the response
post("/hello", (request, response) => "You're the POST master!");
value app = Application {
assets = serve("assets");
};
app.run();
}
In addition to basic handlers, gyokuro allows you to bind GET/POST data directly to function parameters, and return an object that represents your response:
shared void run() {
// ...
post("/hello", `postHandler`);
// ...
}
"Advanced handlers have more flexible parameters, you're
not limited to `Request` and `Response`, you can bind
GET/POST values directly to handler parameters!
The returned value will be written to the response."
String postHandler(Float float, Integer? optionalInt, String who = "world") {
// `float` is required, `optionalInt` is optional and
// `who` will be defaulted to "world" if it's not in POST data.
return "Hello, " + who + "!\n";
}
GET/POST values are mapped by name and automatically converted to the correct type. Note that optional types and default values are also supported!
In addition to get
and post
functions, gyokuro supports annotated controllers.
Using annotations, you can easily group related handlers in a same controller.
Let's see how it works on a simple example:
shared void run() {
value app = Application {
// You can use REST-style annotated controllers like this:
controllers = bind(`package gyokuro.demo.rest`, "/rest");
};
app.run();
}
The package gyokuro.demo.rest
will be scanned for classes annotated with controller
.
Each function annotated with route
will be mapped to the corresponding path. For example:
import ceylon.net.http.server {
Response
}
import net.gyokuro.core {
controller,
route
}
route("duck")
controller class SimpleRestController() {
route("talk")
shared void makeDuckTalk(Response resp) {
resp.writeString("Quack world!");
}
}
Will be mapped to http://localhost:8080/rest/duck/talk
.
See the complete documentation for more info.
You can find examples in the demos directory.