HTTP In-Memory Handler
Sometimes you want to compile your program
into one small binary, even including all
the HTML/CSS/JS stuff for the web interface
or just one humble api.md
file to serve.
It's easier and more secure to deploy such binary in comparison to a bunch of files. Also, it's much faster to serve static files to the client from the memory rather than reading them from the disc again and again with the HTTP::StaticFileHandler.
HTTP::InMemoryHandler to the rescue!
Installation
-
Add the dependency to your
shard.yml
:dependencies: in-memory-handler: github: Xanders/in-memory-handler
-
Run
shards install
Usage
There are two options for how to use this library.
Single file
The first one is to serve only one file.
You can provide the optional path
parameter
(defaults to file's name without extension)
and the optional mime
parameter (will be
inferred by Crystal's MIME
module by default).
require "http/server"
require "in-memory-handler"
my_handler = HTTP::InMemoryFileHandler.for("src/api.md", path: "/help", mime: "text/markdown")
server = HTTP::Server.new [my_handler]
server.bind_tcp "0.0.0.0", 8080
server.listen
GET and HEAD HTTP methods are supported. All other methods will lead to 405 Method Not Allowed error.
Note: giving MIME type to Markdown file will not lead to compiling it into HTML, but you can use an extension for yourself.
A folder
The second option is to serve the given folder.
In opposition to single file mode, regular files
will be served with their full names including
extensions, except *.html
files, which will
be served without extensions. For example,
favicon.ico
will be served as /favicon.ico
and help.html
— as /help
.
Subfolders are supported as well. For example,
js/app.js
will be served as /js/app.js
.
The special index.html
will be served without
its name. For example, api/index.html
will
be served at the /api
URL. And index.html
in the root folder will be served as /
.
You can use the prefix
parameter when you want
to serve your files starting from a non-root URL.
For example, api/index.html
with prefix: "/static"
would lead to the /static/api
URL.
require "http/server"
require "in-memory-handler"
my_handler = HTTP::InMemoryDirectoryHandler.for("public", prefix: "/static")
server = HTTP::Server.new [my_handler]
server.bind_tcp "0.0.0.0", 8080
server.listen
Note: In both modes adding an unnecessary /
at the end of the URL (/some/
) will lead to
a 301 Moved Permanently
redirect to the non-/
version (/some
).
This behavior is best for search engines.
Development
I'm using Docker for library development.
If you have Docker available, you can use make
command
to see the help, powered by make-help project.
There are commands for testing, formatting and documentation.
Contributing
- Fork it (https://github.com/Xanders/in-memory-handler/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