Hematite
Usage
# psgi file
use Hematite;
my $app = Hematite.new;
# middleware
$app.use(sub ($ctx, $next) {
# some processing...
# call next
$next($ctx);
# some processing...
});
class TestMiddleware does Callable {
method CALL-ME($ctx, $next) {
$next($ctx);
}
}
$app.use(TestMiddleware.new);
# routes (can define any http method)
$app.GET('/', sub ($ctx) { $ctx.render({'route' => '/'}, 'type' => 'json'); });
#$app.POST('/', sub ($ctx) { $ctx.render({'route' => '/'}, 'type' => 'json'); });
#$app.METHOD('get', '/', sub ($ctx) { $ctx.render({'route' => '/'}, 'type' => 'json'); });
# route with middleware
$app.GET(
'/with-middleware',
[sub ($ctx, $next) { say 'route middleware'; $next($ctx); }],
sub ($ctx) { $ctx.render({'route' => '/with-middleware'}, 'type' => 'json'); }
);
# route with placeholders/captures
$app.GET(
'/captures/:c1',
sub {
say({
'captures' => $ctx.captures,
'named-captures' => $ctx.named-captures
});
}
);
# route rendering json
$app.GET(
'/json',
sub ($ctx) {
$ctx.render-json(
{'hello' => 'world'},
);
}
);
# route rendering template
$app.GET(
'/template',
sub ($ctx) {
$ctx.render(
'hello',
data => { name => 'world', }
);
}
);
# route rendering inline template/string
$app.GET(
'/template-inline',
sub ($ctx) {
$ctx.render(
'hello {{ name }}',
inline => True,
data => { name => 'world', }
);
}
);
# groups
my $group = $app.group('/group');
$group.GET('/', sub ($ctx) { $ctx.render({'group' => 1}); });
$app;
start crust
crustup [psgi file]
using a more OO approach
class ExampleMiddleware does Hematite::Middleware {
method CALL-ME {
say 'example-middleware';
return self.next;
}
}
class ExampleAction does Hematite::Action {
method middleware {
return [
ExampleMiddleware.create,
];
}
method CALL-ME {
return self.render('example action', inline => True);
}
}
class App is Hematite::App {
method startup {
self.use(ExampleMiddleware.create);
self.GET('/', ExampleAction.create);
self.POST('/', 'ExampleAction');
}
}
context helpers
class Middleware does Hematite::Middleware {
method CALL-ME {
self.add-helper('xpty', sub ($ctx) {
# do something...
});
self.next;
self.remove-helper('xpty');
}
}
my $app = Hematite::App.new;
# register global context helper
$app.context-helper('xpto', sub ($ctx) { say 'helper...'; });
# register context helpers, directly in the context
$app.use(sub ($ctx, $next) {
$ctx.add-helper('xptz', sub ($ctx) {
# do something...
});
$next($ctx);
$ctx.remove-helper('xptz');
});
$app.use(Middleware.create);
# just call the helper from the context
$app.GET('/', sub ($ctx) {
$ctx.xpto;
$ctx.xptz;
$ctx.xpty;
});
websockets
my $app = Hematite::App.new;
$app.WS('/websocket', sub ($ctx) {
$ctx.on('ready', sub {
$ctx.log.info('websocket ready');
for 1..10 -> $idx {
$ctx.send('message', "ping {$idx}");
}
$ctx.send('close');
});
$ctx.on('message', sub ($text) {
$ctx.log.info('received: ' ~ $text);
});
$ctx.on('close', sub {
$ctx.log.info('websocket closed');
});
});
# OR
class WSAction does Hematite::Action {
method CALL-ME {
self.on('ready', sub {
self.log.info('websocket ready');
for 1..10 -> $idx {
self.send('message', "ping {$idx}");
}
self.send('close');
});
self.on('message', sub ($text) {
self.log.info('received: ' ~ $text);
});
self.on('close', sub {
self.log.info('websocket closed');
});
}
}
$app.WS('/websocket2', WSAction);
TODO
Contributing
- Fork it ( https://github.com/[your-github-name]/raku-hematite/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors