Top Level Namespace

Defined in:

Constant Summary

CONTENT_FOR_BLOCKS = Hash(String, Tuple(String, Proc(String))).new
FILTER_METHODS = ["get", "post", "put", "patch", "delete", "options", "all"] of ::String
HTTP_METHODS = ["get", "post", "put", "patch", "delete", "options"] of ::String

Kemal DSL is defined here and it's baked into global scope. The DSL currently consists of

  • get post put patch delete options
  • WebSocket(ws)
  • before_*
  • error

Method Summary

Macro Summary

Method Detail

def add_handler(handler) #

Adds given Kemal::Handler to handlers chain. There are 5 handlers by default and all the custom handlers goes between the first 4 and the last Kemal::RouteHandler.

  • Kemal::InitHandler
  • Kemal::CommonLogHandler
  • Kemal::CommonExceptionHandler
  • Kemal::StaticFileHandler
  • Here goes custom handlers
  • Kemal::RouteHandler

def after_all(path = "*", &block : HTTP::Server::Context -> _) #

def after_delete(path = "*", &block : HTTP::Server::Context -> _) #

def after_get(path = "*", &block : HTTP::Server::Context -> _) #

def after_options(path = "*", &block : HTTP::Server::Context -> _) #

def after_patch(path = "*", &block : HTTP::Server::Context -> _) #

def after_post(path = "*", &block : HTTP::Server::Context -> _) #

def after_put(path = "*", &block : HTTP::Server::Context -> _) #

def before_all(path = "*", &block : HTTP::Server::Context -> _) #

def before_delete(path = "*", &block : HTTP::Server::Context -> _) #

def before_get(path = "*", &block : HTTP::Server::Context -> _) #

def before_options(path = "*", &block : HTTP::Server::Context -> _) #

def before_patch(path = "*", &block : HTTP::Server::Context -> _) #

def before_post(path = "*", &block : HTTP::Server::Context -> _) #

def before_put(path = "*", &block : HTTP::Server::Context -> _) #

def delete(path, &block : HTTP::Server::Context -> _) #

def error(status_code, &block : HTTP::Server::Context, Exception -> _) #

def get(path, &block : HTTP::Server::Context -> _) #

def gzip(status : Bool = false) #

Configures an HTTP::Server::Response to compress the response output, either using gzip or deflate, depending on the Accept-Encoding request header. It's disabled by default.


def headers(env, additional_headers) #

Helper for easily modifying response headers. This can be used to modify a response header with the given hash.

def call(env)

headers(env, {"custom-header" => "This is a custom value"})

end


def log(message) #

Logs the output via logger. This is the built-in Kemal::CommonLogHandler by default which uses STDOUT.


def logger(logger) #

This is used to replace the built-in Kemal::CommonLogHandler with a custom logger.

A custom logger must inherit from Kemal::BaseLogHandler and must implement call(env), write(message) methods.

class MyCustomLogger < Kemal::BaseLogHandler

def call(env)
  puts "I'm logging some custom stuff here."
  call_next(env) # => This calls the next handler
end

# This is used from `log` method.
def write(message)
  STDERR.puts message # => Logs the output to STDERR
end

end

Now that we have a custom logger here's how we use it

logger MyCustomLogger.new


def logging(status) #

Enables / Disables logging. This is enabled by default.

logging false


def options(path, &block : HTTP::Server::Context -> _) #

def patch(path, &block : HTTP::Server::Context -> _) #

def post(path, &block : HTTP::Server::Context -> _) #

def public_folder(path) #

Sets public folder from which the static assets will be served. By default this is /public not src/public.


def put(path, &block : HTTP::Server::Context -> _) #

def render_404 #

def render_500(context, backtrace, verbosity) #

def send_file(env, path : String, mime_type : String? = nil) #

Send a file with given path and default application/octet-stream mime_type.

send_file env, "./path/to/file"

Optionally you can override the mime_type

send_file env, "./path/to/file", "image/jpeg"


def send_file(env, data : Slice(UInt8), mime_type : String? = nil) #

Send a file with given data and default application/octet-stream mime_type.

send_file env, data_slice

Optionally you can override the mime_type

send_file env, data_slice, "image/jpeg"


def serve_static(status : Bool | Hash) #

Enables / Disables static file serving. This is enabled by default.

serve_static false

Static server also have some advanced customization options like dir_listing and gzip.

serve_static {"gzip" => true, "dir_listing" => false}


def ws(path, &block : HTTP::WebSocket, HTTP::Server::Context -> Void) #

Macro Detail

macro content_for(key, file = __FILE__) #

content_for is a set of helpers that allows you to capture blocks inside views to be rendered later during the request. The most common use is to populate different parts of your layout from your view.

The currently supported engines are: ecr and slang.

Usage

You call content_for, generally from a view, to capture a block of markup giving it an identifier:

# index.ecr
<% content_for "some_key" do %>
  <chunk of="html">...</chunk>
<% end %>

Then, you call yield_content with that identifier, generally from a layout, to render the captured block:

# layout.ecr
<%= yield_content "some_key" %>

And How Is This Useful?

For example, some of your views might need a few javascript tags and stylesheets, but you don't want to force this files in all your pages. Then you can put <%= yield_content :scripts_and_styles %> on your layout, inside the <head> tag, and each view can call content_for setting the appropriate set of tags that should be added to the layout.


macro halt(env, status_code = 200, response = "") #

Halt execution with the current context. Returns 200 and an empty response by default.

halt env, status_code: 403, response: "Forbidden"


macro render(filename, layout) #

Render view with a layout as the superview.

render "src/views/index.ecr", "src/views/layout.ecr"


macro render(filename) #

Render view with the given filename.


macro yield_content(key) #

Yields content for the given key if a content_for block exists for that key.