- Crystal 1.14.0 support π
- Windows support #690. Thanks @sdogruyol π
- Directory Listing: Add UTF-8 Charset to the response Content type #679. Thanks @alexkutsan @Sija π
- Use context instead of response in static_headers helper #681. Thanks @sdogruyol π
- Crystal 1.12.0 support π
- Allow HTTP::Server::Context#redirect to take an URL #659. Thanks @xendk π
- Bump
exception_page
dependency #669. Thanks @Sija π - Add message support to
Kemal::Exceptions::CustomException
#671. Thanks @sdogruyol π - Add
Date
header to HTTP responses #676. Thanks @Sija π
- Crystal 1.8.0 support π
- Fix multiple logger handlers when custom logger is used #653. Thanks @aravindavk π
- Add
Kemal::OverrideMethodHandler
#651. Thanks @sdogruyol π HeadRequestHandler
: run GET handler and don't return the body #655. Thanks @compumike π
- Crystal 1.6.0 support π
- Disable signal trap for usage Kemal with other tools #642. Thanks @le0pard π
- Bump exception_page shard to v0.3.0 #645. Thanks @Sija π
- (Security) Omitting filters fix for lowercase methods requests #647. Thanks @sdogruyol @SlayerShadow π
-
Crystal 1.5.0 support π
-
Eliminated several seconds of delay when loading big mp4 file. Thanks @Athlon64 π
-
Fix
content_for
failing to capture the correct block input #639. Thanks @sdogruyol π -
Closes response by default in
HTTP::Server::Context#redirect
#641. Thanks @cyangle π -
Enable option for
index.html
to be a directories default #640. Thanks @ukd1 πYou can enable it via:
serve_static({"dir_index" => true})
- Fix content rendering #631. Thanks @matthewmcgarvey π
- Remove Kilt #618. Thanks @sdogruyol π
- Ignore
HTTP::Server::Response
patching for crystal >= 1.3.0 #628. Thanks @SamantazFox π
- You can now set your own application name for startup message #606. Thanks @aravindavk π
- Add array of paths support for before/after filters #605. Thanks @sdogruyol π
- Fixed executing filters when before and after is defined at the same time #612. Thanks @mamantoha π
- Set content type to text/html for 500 exceptions #616. Thanks @sdogruyol π
- Crystal 1.0.0 support π
- Update Radix to use latest 0.4.0 #596. Thanks @luislavena π
- Use latest version of Ameba dependency (dev) #597. Thanks @luislavena π
- Fix
StaticFileHandler
failing spec #599. Thanks @jinn999 π
- Crystal 0.35.x support π Thanks @bcardiff π
- Fix issues with responding with long strings #576. Thanks @mamantoha π
- Fix broken WebSocket support in 0.35.0 #577. Thanks @mamantoha π
- Allow to set optional response body on redirects #561. Thanks @mamantoha π
- Fix process request when a response already closed #550. Thanks @mamantoha π
- Switch to new Ameba repository #549. Thanks @mamantoha π
- Check for
KEMAL_ENV
variable already inConfig#initialize
#552. Thanks @Sija π - Cleanup Ameba warnings #551. Thanks @Sija π
- Flush io buffer after each write to log #554. Thanks @mang π
- Crystal 0.30.0 support π #548 and #544. Thanks @bcardiff and @straight-shoota π
- Add support for serving files greater than 2^31 bytes #546. Thanks @omarroth π
- Properly measure request time using
Time.monotonic
#527. Thanks @spinscale π
-
Add option to config to parse or not command line parameters #483. Thanks @diegogub π
-
Allow to set filename for
send_file
#512. Thanks @mamantoha πsend_file env, "./asset/image.jpeg", filename: "image.jpg"
-
Set
status_code
before response #513. Thanks @mamantohoa π -
Use Crystal MIME registry. #516 Thanks @Sija π
- Fix
params.files
memoization #503. Thanks @mamantoha π
- Crystal 0.27.0 support.
- [breaking change] Added back
env.params.files
.
Here's a fully working sample for reading a image file upload image1
and saving it under public/uploads
.
post "/upload" do |env|
file = env.params.files["image1"].tempfile
file_path = ::File.join [Kemal.config.public_folder, "uploads/", File.basename(file.path)]
File.open(file_path, "w") do |f|
IO.copy(file, f)
end
"Upload ok"
end
To test
curl -F "image1=@/Users/serdar/Downloads/kemal.png" http://localhost:3000/upload
- Cache HTTP routes to increase performance π #493
-
[breaking change] Removed
env.params.files
. You can use Crystal's built-inHTTP::FormData.parse
instead:post "/upload" do |env| HTTP::FormData.parse(env.request) do |upload| filename = file.filename if !filename.is_a?(String) "No filename included in upload" else file_path = ::File.join [Kemal.config.public_folder, "uploads/", filename] File.open(file_path, "w") do |f| IO.copy(file.tmpfile, f) end "Upload OK" end end
-
[breaking change] From now on to access dynamic url params in a WebSocket route you have to use:
ws "/:id" do |socket, context| id = context.ws_route_lookup.params["id"] end
-
[breaking change] Removed
_method
magic param. -
Added new exception page #466. Thanks @mamantoha π
-
Support custom port binding. Thanks @straight-shoota π
Kemal.run do |config| server = config.server.not_nil! server.bind_tcp "127.0.0.1", 3000, reuse_port: true server.bind_tcp "0.0.0.0", 3001, reuse_port: true end
- Crystal 0.25.0 support π
- Add
Kemal::Context.get?
to safely access context storage π - [Security] Don't serve 404 image dynamically π
- Disable
X-Powered-By
header #449. Thanks @Blacksmoke16 π
- Crystal 0.24.1 support π
- Only return string from route.#408 thanks @crisward π
- Don't crash on empty path when compiled in --release. #407 thanks @crisward π
- Rename
Kemal::CommonLogHandler
toKemal::LogHandler
andKemal::CommonExceptionHandler
toKemal::ExceptionHandler
. - Allow videos to be opened with correct mime type. #406 thanks @crisward π
- Add webm mime type.#413 thanks @reindeer-cafe π
-
Dynamically insert handlers πͺ Fixes #376.
-
Add context to WebSocket. This allows one to use
HTTP::Server::Context
inws
declarations π Fixes #349.ws "/:room_name" do |socket, env| env.params.url["room_name"] end
-
Add support for customizing the headers of built-in
Kemal::StaticFileHandler
π¨ Useful for supportingCORS
for single page applications π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
-
Allow
%w
in Handler macros #385. Thanks @will π -
Security:
X-Content-Type-Options: nosniff
for static files. Fixes #379. Thanks @crisward π -
Performance: Remove tempfile management to OS. This brings 10-15% performance boost to Kemal π
-
Crystal 0.23.0 support! As always, Kemal is compatible with the latest major release of Crystal π
-
Great news everyone π All handlers are now completely customizable!. Use the default
Kemal
handlers or go wild, it's all up to you β# Don't forget to add `Kemal::RouteHandler::INSTANCE` or your routes won't work! Kemal.config.handlers = [Kemal::InitHandler.new, YourHandler.new, Kemal::RouteHandler::INSTANCE]
You can also insert a handler into a specific position.
# This adds MyCustomHandler instance to 1 position. # Be aware that the index starts from 0. add_handler MyCustomHandler.new, 1
-
Updated Kilt to v0.4.0.
-
Make
Route
aStruct
. This improves the performance of route declarations.
- Return no body for head route fixes #323. (thanks @crisward)
- Update Radix to
v0.3.8
. (thanks @waghanza) - User defined context store types. (thanks @neovitange)
class User
property name
end
add_context_storage_type(User)
- Prevent
send_file
returning filesize. (thanks @crisward) - Don't call setup in
config#add_filter_handler
fixes #338.
- Remove
Gzip::Header
monkey patch since it's fixed inCrystal 0.21.1
.
- Fix Gzip in Kemal Seems broken for static files #316. This was caused by
Gzip::Writer
inCrystal 0.21.0
and currently mitigated by monkey patchingGzip::Header
.
- Crystal 0.21.0 support
- Drop
multipart.cr
dependency.multipart
support is now built-into Crystal <3 - Since Crystal 0.21.0 comes built-in with
multipart
there are some improvements and deprecations. meta
has been removed fromFileUpload
and it has the following properties:tmpfile
: This is temporary file for file upload. Useful for saving the upload file.filename
: File name of the file upload. (logo.png, images.zip e.g)headers
: Headers for the file upload.creation_time
: Creation time of the file upload.modification_time
: Last Modification time of the file upload.read_time
: Read time of the file upload.size
: Size of the file upload.
-
Simpler file upload. File uploads can now be access from
HTTP::Server::Context
likeenv.params.files["filename"]
, which exposes following properties.tmpfile
: This is temporary file for file upload. Useful for saving the upload file.tmpfile_path
: File path oftmpfile
.filename
: File name of the file upload. (logo.png, images.zip e.g)meta
: Meta information for the file upload.headers
: Headers for the file upload.
Here's a fully working sample for reading a image file upload
image1
and saving it underpublic/uploads
.post "/upload" do |env| file = env.params.files["image1"].tmpfile file_path = ::File.join [Kemal.config.public_folder, "uploads/", file.filename] File.open(file_path, "w") do |f| IO.copy(file, f) end "Upload ok" end
To test
curl -F "image1=@/Users/serdar/Downloads/kemal.png" http://localhost:3000/upload
-
RF7233 support a.k.a file streaming. #299 (thanks @denysvitali)
-
Update Radix to 0.3.7. Fixes #293
-
Configurable startup / shutdown logging. #291 and #292 (thanks @twisterghost).
- Update multipart.cr to 0.1.2. Fixes #285 related to multipart.cr
- Support for Crystal 0.20.3
- Add
Kemal.stop
. Fixes #269. HTTP::Handler
is not a class anymore, it's a module. See https://github.com/crystal-lang/crystal/releases/tag/0.20.3
- Handle missing 404 image. Fixes #263
- Remove basic auth middleware from core and move to kemalcr/kemal-basic-auth.
- Use
body.gets_to_end
forparse_json
. Fixes #260. - Update Radix to 0.3.5 and lock pessimistically. (thanks @luislavena)
- Treat
HTTP::Request
body as anIO
. Fixes #257
-
Reimplemented Request middleware / filter routing.
Now all requests will first go through the Middleware stack then Filters (
before_*
) and will finally reach the matching route.Which is illustrated as:
Request -> Middleware -> Filter -> Route
-
Rename
return_with
ashalt
. -
Route declaration must start with
/
. Fixes #242 -
Set default exception
Content-Type
totext/html
. Fixes #202 -
Add
only
andexclude
paths forKemal::Handler
. This change requires that all handlers must inherit fromKemal::Handler
.For example this handler will only work on
/
path. By default the HTTP method isGET
.class OnlyHandler < Kemal::Handler only ["/"] def call(env) return call_next(env) unless only_match?(env) puts "If the path is / i will be doing some processing here." end end
The handlers using
exclude
will work on the paths that isn't specified. For example this handler will work on any routes other than/
.class ExcludeHandler < Kemal::Handler exclude ["/"] def call(env) return call_next(env) unless only_match?(env) puts "If the path is NOT / i will be doing some processing here." end end
-
Close response on
halt
. (thanks @samueleaton). -
Update Radix to
v0.3.4
. -
error
handler now also yields error. For example you can get the error mesasage like:error 500 do |env, err| err.message end
-
Update
multipart.cr
tov0.1.1
-
Improved Multipart support with more info on parsed files.
parse_multipart(env)
now yields anUploadFile
object which has the following properties:field
,data
,meta
andheaders
.post "/upload" do |env| parse_multipart(env) do |f| image1 = f.data if f.field == "image1" image2 = f.data if f.field == "image2" puts f.meta puts f.headers "Upload complete" end end
-
Multipart support <3 (thanks @RX14). Now you can handle file uploads.
post "/upload" do |env| parse_multipart(env) do |field, data| image1 = data if field == "image1" image2 = data if field == "image2" "Upload complete" end end
-
Make session configurable. Now you can specify session name and expire time with:
Kemal.config.session["name"] = "your_app" Kemal.config.session["expire_time"] = 48.hours
-
Session now supports more types. (
String
,Int32
,Float64
,Bool
) -
Add
gzip
helper to enable / disable gzip compression on responses. -
Static file caching with etag and gzip (thanks @crisward)
-
Kemal.run
now accepts port to listen.
- Don't forget to
call_next
onNullLogHandler
- Add context store.
KEMAL_ENV
respects toKemal.config.env
and needs to be explicitly set.Kemal::InitHandler
is introduced. Adds initial configuration, headers likeX-Powered-By
.- Add
send_file
to helpers. - Add mime types.
- Fix parsing JSON params when "charset" is present in
Content-Type
header. - Use http-only cookie for session.
- Inject
STDOUT
by default inCommonLogHandler
.