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 : HTTP::Handler, position : Int32) #

[View source]
def add_handler(handler : HTTP::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.


[View source]
def after_all(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_all(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_delete(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_delete(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_get(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_get(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_options(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_options(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_patch(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_patch(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_post(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_post(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def after_put(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def after_put(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_all(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_all(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_delete(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_delete(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_get(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_get(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_options(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_options(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_patch(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_patch(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_post(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_post(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def before_put(path : String = "*", &block : HTTP::Server::Context -> _) #

[View source]
def before_put(paths : Array(String), &block : HTTP::Server::Context -> _) #

[View source]
def delete(path : String, &block : HTTP::Server::Context -> _) #

[View source]
def error(status_code : Int32, &block : HTTP::Server::Context, Exception -> _) #

[View source]
def get(path : String, &block : HTTP::Server::Context -> _) #

[View source]
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.

Disabled by default.


[View source]
def headers(env : HTTP::Server::Context, additional_headers : Hash(String, String)) #

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

def call(env)
  headers(env, {"X-Custom-Header" => "This is a custom value"})
end

[View source]
def log(message : String) #

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


[View source]
def logger(logger : Kemal::BaseLogHandler) #

This is used to replace the built-in Kemal::LogHandler 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

[View source]
def logging(status : Bool) #

Enables / Disables logging. This is enabled by default.

logging false

[View source]
def options(path : String, &block : HTTP::Server::Context -> _) #

[View source]
def patch(path : String, &block : HTTP::Server::Context -> _) #

[View source]
def post(path : String, &block : HTTP::Server::Context -> _) #

[View source]
def public_folder(path : String) #

Sets public folder from which the static assets will be served.

By default this is /public not src/public.


[View source]
def put(path : String, &block : HTTP::Server::Context -> _) #

[View source]
def render_404 #

[View source]
def render_500(context, exception, verbosity) #

[View source]
def send_file(env : HTTP::Server::Context, path : String, mime_type : String | Nil = nil, *, filename : String | Nil = nil, disposition : String | Nil = nil) #

Send a file with given path and base the mime-type on the file extension or 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"

Also you can set the filename and the disposition

send_file env, "./path/to/file", filename: "image.jpg", disposition: "attachment"

[View source]
def send_file(env : HTTP::Server::Context, data : Slice(UInt8), mime_type : String | Nil = nil, *, filename : String | Nil = nil, disposition : String | Nil = 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"

Also you can set the filename and the disposition

send_file env, data_slice, filename: "image.jpg", disposition: "attachment"

[View source]
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}

[View source]
def static_headers(&headers : HTTP::Server::Response, String, File::Info -> Void) #

Adds headers to Kemal::StaticFileHandler. This is especially useful for CORS.

static_headers do |response, filepath, filestat|
  if filepath =~ /\.html$/
    response.headers.add("Access-Control-Allow-Origin", "*")
  end
  response.headers.add("Content-Size", filestat.size.to_s)
end

[View source]
def ws(path : String, &block : HTTP::WebSocket, HTTP::Server::Context -> Void) #

[View source]

Macro Detail

macro add_context_storage_type(type) #

Extends context storage with user defined types.

class User
  property name
end

add_context_storage_type(User)

[View source]
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 tag, and each view can call content_for setting the appropriate set of tags that should be added to the layout.


[View source]
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"

[View source]
macro render(filename, layout) #

Render view with a layout as the superview.

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

[View source]
macro render(filename) #

Render view with the given filename.


[View source]
macro yield_content(key) #

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


[View source]