Prettify docs (#410)

This commit is contained in:
Sijawusz Pur Rahnama 2017-10-06 13:53:53 +02:00 committed by Serdar Dogruyol
parent c2da18ed38
commit 210e2c0801
16 changed files with 129 additions and 85 deletions

View file

@ -7,26 +7,26 @@ require "./kemal/ext/*"
require "./kemal/helpers/*" require "./kemal/helpers/*"
module Kemal module Kemal
# Overload of self.run with the default startup logging # Overload of `self.run` with the default startup logging.
def self.run(port : Int32?) def self.run(port : Int32?)
self.run port do self.run port do
log "[#{config.env}] Kemal is ready to lead at #{config.scheme}://#{config.host_binding}:#{config.port}" log "[#{config.env}] Kemal is ready to lead at #{config.scheme}://#{config.host_binding}:#{config.port}"
end end
end end
# Overload of self.run without port - fixex #399 # Overload of `self.run` without port.
def self.run def self.run
self.run(nil) self.run(nil)
end end
# Overload of self.run to allow just a block # Overload of `self.run` to allow just a block.
def self.run(&block) def self.run(&block)
self.run nil, &block self.run nil, &block
end end
# The command to run a `Kemal` application. # The command to run a `Kemal` application.
# The port can be given to `#run` but is optional. #
# If not given Kemal will use `Kemal::Config#port` # If *port* is not given Kemal will use `Kemal::Config#port`
def self.run(port : Int32? = nil, &block) def self.run(port : Int32? = nil, &block)
Kemal::CLI.new Kemal::CLI.new
config = Kemal.config config = Kemal.config
@ -61,7 +61,7 @@ module Kemal
config.server ||= HTTP::Server.new(config.host_binding, config.port, config.handlers) config.server ||= HTTP::Server.new(config.host_binding, config.port, config.handlers)
{% if !flag?(:without_openssl) %} {% if !flag?(:without_openssl) %}
config.server.not_nil!.tls = config.ssl config.server.not_nil!.tls = config.ssl
{% end %} {% end %}
config.running = true config.running = true

View file

@ -1,5 +1,5 @@
module Kemal module Kemal
# Kemal::CommonExceptionHandler handles all the exceptions including 404, custom errors and 500. # Handles all the exceptions, including 404, custom errors and 500.
class CommonExceptionHandler class CommonExceptionHandler
include HTTP::Handler include HTTP::Handler
INSTANCE = new INSTANCE = new

View file

@ -1,5 +1,5 @@
module Kemal module Kemal
# Kemal::CommonLogHandler uses STDOUT by default and handles the logging of request/response process time. # Uses `STDOUT` by default and handles the logging of request/response process time.
class CommonLogHandler < Kemal::BaseLogHandler class CommonLogHandler < Kemal::BaseLogHandler
@io : IO @io : IO

View file

@ -1,9 +1,10 @@
module Kemal module Kemal
# Kemal::Config stores all the configuration options for a Kemal application. # Stores all the configuration options for a Kemal application.
# It's a singleton and you can access it like. # It's a singleton and you can access it like.
# #
# Kemal.config # ```
# # Kemal.config
# ```
class Config class Config
INSTANCE = Config.new INSTANCE = Config.new
HANDLERS = [] of HTTP::Handler HANDLERS = [] of HTTP::Handler
@ -12,9 +13,9 @@ module Kemal
ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String
{% if flag?(:without_openssl) %} {% if flag?(:without_openssl) %}
@ssl : Bool? @ssl : Bool?
{% else %} {% else %}
@ssl : OpenSSL::SSL::Context::Server? @ssl : OpenSSL::SSL::Context::Server?
{% end %} {% end %}
getter custom_handler_position getter custom_handler_position

View file

@ -1,5 +1,7 @@
# Kemal DSL is defined here and it's baked into global scope. # Kemal DSL is defined here and it's baked into global scope.
# The DSL currently consists of #
# The DSL currently consists of:
#
# - get post put patch delete options # - get post put patch delete options
# - WebSocket(ws) # - WebSocket(ws)
# - before_* # - before_*

View file

@ -1,5 +1,6 @@
# HTTP::Server::Context is the class which holds HTTP::Request and HTTP::Server::Response alongside with # `HTTP::Server::Context` is the class which holds `HTTP::Request` and
# information such as request params, request/response content_type, session e.g # `HTTP::Server::Response` alongside with information such as request params,
# request/response content_type, session data and alike.
# #
# Instances of this class are passed to an `HTTP::Server` handler. # Instances of this class are passed to an `HTTP::Server` handler.
class HTTP::Server class HTTP::Server

View file

@ -10,7 +10,7 @@ module Kemal
Kemal.config.add_filter_handler(self) Kemal.config.add_filter_handler(self)
end end
# The call order of the filters is before_all -> before_x -> X -> after_x -> after_all # The call order of the filters is `before_all -> before_x -> X -> after_x -> after_all`.
def call(context : HTTP::Server::Context) def call(context : HTTP::Server::Context)
return call_next(context) unless context.route_defined? return call_next(context) unless context.route_defined?
call_block_for_path_type("ALL", context.request.path, :before, context) call_block_for_path_type("ALL", context.request.path, :before, context)
@ -24,7 +24,8 @@ module Kemal
context context
end end
# :nodoc: This shouldn't be called directly, it's not private because I need to call it for testing purpose since I can't call the macros in the spec. # :nodoc: This shouldn't be called directly, it's not private because
# I need to call it for testing purpose since I can't call the macros in the spec.
# It adds the block for the corresponding verb/path/type combination to the tree. # It adds the block for the corresponding verb/path/type combination to the tree.
def _add_route_filter(verb : String, path, type, &block : HTTP::Server::Context -> _) def _add_route_filter(verb : String, path, type, &block : HTTP::Server::Context -> _)
lookup = lookup_filters_for_path_type(verb, path, type) lookup = lookup_filters_for_path_type(verb, path, type)
@ -35,12 +36,16 @@ module Kemal
end end
end end
# This can be called directly but it's simpler to just use the macros, it will check if another filter is not already defined for this verb/path/type and proceed to call `add_route_filter` # This can be called directly but it's simpler to just use the macros,
# it will check if another filter is not already defined for this
# verb/path/type and proceed to call `add_route_filter`
def before(verb : String, path : String = "*", &block : HTTP::Server::Context -> _) def before(verb : String, path : String = "*", &block : HTTP::Server::Context -> _)
_add_route_filter verb, path, :before, &block _add_route_filter verb, path, :before, &block
end end
# This can be called directly but it's simpler to just use the macros, it will check if another filter is not already defined for this verb/path/type and proceed to call `add_route_filter` # This can be called directly but it's simpler to just use the macros,
# it will check if another filter is not already defined for this
# verb/path/type and proceed to call `add_route_filter`
def after(verb : String, path : String = "*", &block : HTTP::Server::Context -> _) def after(verb : String, path : String = "*", &block : HTTP::Server::Context -> _)
_add_route_filter verb, path, :after, &block _add_route_filter verb, path, :after, &block
end end

View file

@ -1,5 +1,6 @@
module Kemal module Kemal
# `Kemal::Handler` is a subclass of `HTTP::Handler`. # `Kemal::Handler` is a subclass of `HTTP::Handler`.
#
# It adds `only`, `only_match?`, `exclude`, `exclude_match?`. # It adds `only`, `only_match?`, `exclude`, `exclude_match?`.
# These methods are useful for custom handlers for conditional execution. # These methods are useful for custom handlers for conditional execution.
class Handler class Handler
@ -32,14 +33,16 @@ module Kemal
# #
# However this is not done automatically. All handlers must inherit from `Kemal::Handler`. # However this is not done automatically. All handlers must inherit from `Kemal::Handler`.
# #
# class OnlyHandler < Kemal::Handler # ```
# only ["/"] # class OnlyHandler < Kemal::Handler
# only ["/"]
# #
# def call(env) # def call(env)
# return call_next(env) unless only_match?(env) # return call_next(env) unless only_match?(env)
# puts "If the path is / i will be doing some processing here." # puts "If the path is / i will be doing some processing here."
# end # end
# end # end
# ```
def only_match?(env : HTTP::Server::Context) def only_match?(env : HTTP::Server::Context)
@@only_routes_tree.find(radix_path(env.request.method, env.request.path)).found? @@only_routes_tree.find(radix_path(env.request.method, env.request.path)).found?
end end
@ -51,14 +54,16 @@ module Kemal
# #
# However this is not done automatically. All handlers must inherit from `Kemal::Handler`. # However this is not done automatically. All handlers must inherit from `Kemal::Handler`.
# #
# class ExcludeHandler < Kemal::Handler # ```
# exclude ["/"] # class ExcludeHandler < Kemal::Handler
# exclude ["/"]
# #
# def call(env) # def call(env)
# return call_next(env) if exclude_match?(env) # return call_next(env) if exclude_match?(env)
# puts "If the path is not / i will be doing some processing here." # puts "If the path is not / i will be doing some processing here."
# end # end
# end # end
# ```
def exclude_match?(env : HTTP::Server::Context) def exclude_match?(env : HTTP::Server::Context)
@@exclude_routes_tree.find(radix_path(env.request.method, env.request.path)).found? @@exclude_routes_tree.find(radix_path(env.request.method, env.request.path)).found?
end end

View file

@ -1,13 +1,13 @@
# Adds given Kemal::Handler to handlers chain. # Adds given `Kemal::Handler` to handlers chain.
# There are 5 handlers by default and all the custom handlers # There are 5 handlers by default and all the custom handlers
# goes between the first 4 and the last `Kemal::RouteHandler`. # goes between the first 4 and the last `Kemal::RouteHandler`.
# #
# - Kemal::InitHandler # - `Kemal::InitHandler`
# - Kemal::CommonLogHandler # - `Kemal::CommonLogHandler`
# - Kemal::CommonExceptionHandler # - `Kemal::CommonExceptionHandler`
# - Kemal::StaticFileHandler # - `Kemal::StaticFileHandler`
# - Here goes custom handlers # - Here goes custom handlers
# - Kemal::RouteHandler # - `Kemal::RouteHandler`
def add_handler(handler : HTTP::Handler) def add_handler(handler : HTTP::Handler)
Kemal.config.add_handler handler Kemal.config.add_handler handler
end end
@ -17,6 +17,7 @@ def add_handler(handler : HTTP::Handler, position : Int32)
end end
# Sets public folder from which the static assets will be served. # Sets public folder from which the static assets will be served.
#
# By default this is `/public` not `src/public`. # By default this is `/public` not `src/public`.
def public_folder(path : String) def public_folder(path : String)
Kemal.config.public_folder = path Kemal.config.public_folder = path
@ -31,7 +32,9 @@ end
# Enables / Disables logging. # Enables / Disables logging.
# This is enabled by default. # This is enabled by default.
# #
# logging false # ```
# logging false
# ```
def logging(status : Bool) def logging(status : Bool)
Kemal.config.logging = status Kemal.config.logging = status
end end
@ -41,22 +44,26 @@ end
# A custom logger must inherit from `Kemal::BaseLogHandler` and must implement # A custom logger must inherit from `Kemal::BaseLogHandler` and must implement
# `call(env)`, `write(message)` methods. # `call(env)`, `write(message)` methods.
# #
# class MyCustomLogger < Kemal::BaseLogHandler # ```
# class MyCustomLogger < Kemal::BaseLogHandler
# #
# def call(env) # def call(env)
# puts "I'm logging some custom stuff here." # puts "I'm logging some custom stuff here."
# call_next(env) # => This calls the next handler # 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 # 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 # Now that we have a custom logger here's how we use it
# #
# logger MyCustomLogger.new # ```
# logger MyCustomLogger.new
# ```
def logger(logger : Kemal::BaseLogHandler) def logger(logger : Kemal::BaseLogHandler)
Kemal.config.logger = logger Kemal.config.logger = logger
Kemal.config.add_handler logger Kemal.config.add_handler logger
@ -65,12 +72,16 @@ end
# Enables / Disables static file serving. # Enables / Disables static file serving.
# This is enabled by default. # This is enabled by default.
# #
# ```
# serve_static false # serve_static false
# ```
# #
# Static server also have some advanced customization options like `dir_listing` and # Static server also have some advanced customization options like `dir_listing` and
# `gzip`. # `gzip`.
# #
# ```
# serve_static {"gzip" => true, "dir_listing" => false} # serve_static {"gzip" => true, "dir_listing" => false}
# ```
def serve_static(status : (Bool | Hash)) def serve_static(status : (Bool | Hash))
Kemal.config.serve_static = status Kemal.config.serve_static = status
end end
@ -78,9 +89,11 @@ end
# Helper for easily modifying response headers. # Helper for easily modifying response headers.
# This can be used to modify a response header with the given hash. # 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"}) # def call(env)
# end # headers(env, {"X-Custom-Header" => "This is a custom value"})
# end
# ```
def headers(env : HTTP::Server::Context, additional_headers : Hash(String, String)) def headers(env : HTTP::Server::Context, additional_headers : Hash(String, String))
env.response.headers.merge!(additional_headers) env.response.headers.merge!(additional_headers)
end end
@ -88,11 +101,15 @@ end
# Send a file with given path and base the mime-type on the file extension # Send a file with given path and base the mime-type on the file extension
# or default `application/octet-stream` mime_type. # or default `application/octet-stream` mime_type.
# #
# send_file env, "./path/to/file" # ```
# send_file env, "./path/to/file"
# ```
# #
# Optionally you can override the mime_type # Optionally you can override the mime_type
# #
# send_file env, "./path/to/file", "image/jpeg" # ```
# send_file env, "./path/to/file", "image/jpeg"
# ```
def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = nil) def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = nil)
config = Kemal.config.serve_static config = Kemal.config.serve_static
file_path = File.expand_path(path, Dir.current) file_path = File.expand_path(path, Dir.current)
@ -184,11 +201,15 @@ end
# Send a file with given data and default `application/octet-stream` mime_type. # Send a file with given data and default `application/octet-stream` mime_type.
# #
# send_file env, data_slice # ```
# send_file env, data_slice
# ```
# #
# Optionally you can override the mime_type # Optionally you can override the mime_type
# #
# send_file env, data_slice, "image/jpeg" # ```
# send_file env, data_slice, "image/jpeg"
# ```
def send_file(env : HTTP::Server::Context, data : Slice(UInt8), mime_type : String? = nil) def send_file(env : HTTP::Server::Context, data : Slice(UInt8), mime_type : String? = nil)
mime_type ||= "application/octet-stream" mime_type ||= "application/octet-stream"
env.response.content_type = mime_type env.response.content_type = mime_type
@ -198,14 +219,15 @@ end
# Configures an `HTTP::Server::Response` to compress the response # Configures an `HTTP::Server::Response` to compress the response
# output, either using gzip or deflate, depending on the `Accept-Encoding` request header. # output, either using gzip or deflate, depending on the `Accept-Encoding` request header.
# It's disabled by default. #
# Disabled by default.
def gzip(status : Bool = false) def gzip(status : Bool = false)
add_handler HTTP::CompressHandler.new if status add_handler HTTP::CompressHandler.new if status
end end
# Adds headers to `Kemal::StaticFileHandler`. This is especially useful for `CORS`. # Adds headers to `Kemal::StaticFileHandler`. This is especially useful for `CORS`.
# #
# ```ruby # ```
# static_headers do |response, filepath, filestat| # static_headers do |response, filepath, filestat|
# if filepath =~ /\.html$/ # if filepath =~ /\.html$/
# response.headers.add("Access-Control-Allow-Origin", "*") # response.headers.add("Access-Control-Allow-Origin", "*")

View file

@ -13,16 +13,20 @@ CONTENT_FOR_BLOCKS = Hash(String, Tuple(String, Proc(String))).new
# You call `content_for`, generally from a view, to capture a block of markup # You call `content_for`, generally from a view, to capture a block of markup
# giving it an identifier: # giving it an identifier:
# #
# # index.ecr # ```
# <% content_for "some_key" do %> # # index.ecr
# <chunk of="html">...</chunk> # <% content_for "some_key" do %>
# <% end %> # <chunk of="html">...</chunk>
# <% end %>
# ```
# #
# Then, you call `yield_content` with that identifier, generally from a # Then, you call `yield_content` with that identifier, generally from a
# layout, to render the captured block: # layout, to render the captured block:
# #
# # layout.ecr # ```
# <%= yield_content "some_key" %> # # layout.ecr
# <%= yield_content "some_key" %>
# ```
# #
# ## And How Is This Useful? # ## And How Is This Useful?
# #
@ -53,8 +57,9 @@ end
# Render view with a layout as the superview. # Render view with a layout as the superview.
# #
# render "src/views/index.ecr", "src/views/layout.ecr" # ```
# # render "src/views/index.ecr", "src/views/layout.ecr"
# ```
macro render(filename, layout) macro render(filename, layout)
__content_filename__ = {{filename}} __content_filename__ = {{filename}}
content = render {{filename}} content = render {{filename}}
@ -69,7 +74,9 @@ end
# Halt execution with the current context. # Halt execution with the current context.
# Returns 200 and an empty response by default. # Returns 200 and an empty response by default.
# #
# halt env, status_code: 403, response: "Forbidden" # ```
# halt env, status_code: 403, response: "Forbidden"
# ```
macro halt(env, status_code = 200, response = "") macro halt(env, status_code = 200, response = "")
{{env}}.response.status_code = {{status_code}} {{env}}.response.status_code = {{status_code}}
{{env}}.response.print {{response}} {{env}}.response.print {{response}}
@ -79,12 +86,13 @@ end
# Extends context storage with user defined types. # Extends context storage with user defined types.
# #
# ```
# class User # class User
# property name # property name
# end # end
# #
# add_context_storage_type(User) # add_context_storage_type(User)
# # ```
macro add_context_storage_type(type) macro add_context_storage_type(type)
{{ HTTP::Server::Context::STORE_MAPPINGS.push(type) }} {{ HTTP::Server::Context::STORE_MAPPINGS.push(type) }}
end end

View file

@ -1,6 +1,6 @@
module Kemal module Kemal
# Kemal::InitHandler is the first handler thus initializes the context with default values. # Initializes the context with default values, such as
# Such as *Content-Type*, *X-Powered-By* headers. # *Content-Type* or *X-Powered-By* headers.
class InitHandler class InitHandler
include HTTP::Handler include HTTP::Handler
INSTANCE = new INSTANCE = new

View file

@ -1,7 +1,7 @@
module Kemal module Kemal
# ParamParser parses the request contents including query_params and body # Parses the request contents including query_params and body
# and converts them into a params hash which you can within the environment # and converts them into a params hash which you can use within
# context. # the environment context.
class ParamParser class ParamParser
URL_ENCODED_FORM = "application/x-www-form-urlencoded" URL_ENCODED_FORM = "application/x-www-form-urlencoded"
APPLICATION_JSON = "application/json" APPLICATION_JSON = "application/json"
@ -78,9 +78,9 @@ module Kemal
end end
# Parses JSON request body if Content-Type is `application/json`. # Parses JSON request body if Content-Type is `application/json`.
# If request body is a JSON Hash then all the params are parsed and added into `params`. #
# If request body is a JSON Array it's added into `params` as `_json` and can be accessed # - If request body is a JSON `Hash` then all the params are parsed and added into `params`.
# like params["_json"] # - If request body is a JSON `Array` it's added into `params` as `_json` and can be accessed like `params["_json"]`.
private def parse_json private def parse_json
return unless @request.body && @request.headers["Content-Type"]?.try(&.starts_with?(APPLICATION_JSON)) return unless @request.body && @request.headers["Content-Type"]?.try(&.starts_with?(APPLICATION_JSON))

View file

@ -1,6 +1,7 @@
module Kemal module Kemal
# Route is the main building block of Kemal. # Route is the main building block of Kemal.
# It takes 3 parameters: Method, path and a block to specify #
# It takes 3 parameters: http *method*, *path* and a *handler* to specify
# what action to be done if the route is matched. # what action to be done if the route is matched.
struct Route struct Route
getter method, path, handler getter method, path, handler

View file

@ -1,8 +1,8 @@
require "radix" require "radix"
module Kemal module Kemal
# Kemal::RouteHandler is the main handler which handles all the HTTP requests. Routing, parsing, rendering e.g # Main handler which handles all the HTTP requests.
# are done in this handler. # Routing, parsing, rendering e.g are done in this handler.
class RouteHandler class RouteHandler
include HTTP::Handler include HTTP::Handler
INSTANCE = new INSTANCE = new

View file

@ -1,6 +1,5 @@
module Kemal module Kemal
# Route is the main building block of Kemal. # Takes 2 parameters: *path* and a *handler* to specify
# It takes 3 parameters: Method, path and a block to specify
# what action to be done if the route is matched. # what action to be done if the route is matched.
class WebSocket < HTTP::WebSocketHandler class WebSocket < HTTP::WebSocketHandler
getter proc getter proc

View file

@ -1,5 +1,5 @@
module Kemal module Kemal
# Kemal::WebSocketHandler is used for building a WebSocket route. # Used for building a WebSocket route.
# For each WebSocket route a new handler is created and registered to global handlers. # For each WebSocket route a new handler is created and registered to global handlers.
class WebSocketHandler class WebSocketHandler
include HTTP::Handler include HTTP::Handler