A minimal HTTP framework
Author onetonfoot
0 Stars
Updated Last
2 Years Ago
Started In
October 2019


Build Status Coverage Status

Getting started

It's as simple as

app = App()

app("/path"; method = GET) do request
    reponse = "hello"
    return response


Now visit localhost:8081.

The handler function takes a HTTP.Request and returns a HTTP.Response.

After your handler is called if it's return type isn't a Response it will be made into one by calling create_response. You can overload create_reponse for your specific type to have more control.


This is already defined for AbstractString and AbstractDict, were the Content-Type header is set as text/plain and application/json respectively.

Routing and Query Parameters

Routes can be defined for multiple methods by passing an array

app(handler, "/path"; method = [GET, POST])

They can be parametrized by using the syntax /:x. You can then access the parameters in the handler with.

app("/route/:id", method = [GET, POST]) do request
    params = path_params(request)
    # Dict(:id => value)

Specific routes take priority over variable routes, in other words "/route/1" will be matched before "/route/:id".

Query parameters can be accessed in a similar way.

query = query_params(request)


To serve a file pass the route and a file path.

app("/",  p"index.html")

The MIME type will be inferred from the extension, the supported MIME types can be found here. If the MIME-type is unsupported it can be added to the global MIME_TYPES.


You can server folders using the following syntax

app("/img", p"images"; recursive=true, filter_fn=filepath->true)

filter_fn can be used to remove files you don't want to be served, it should return a boolean.

If given a folder of the following structure.

├── cat.jpeg
└── dog.jpeg

The routes generated would be img/cat.jpeg and img/dog.jpeg.


When instantiating the app you can pass data structure you want to use for the session, by default this will be a Dict. But could be anything you want to use to store state e.g

app = App(session = ReidsSession()) 

The session can then be accessed in the handler.

app("/path") do req
    session = app.session

Since a Dict isn't thread-safe so this will likey change in the future to a different data structure, once parallelism is addressed.


app(ws"/chat_room") do ws
    while isopen(ws)
        # do stuff


Still thinking about the nicest way to implement this suggesting are welcome!


Yet todo but will probably add a CLI using Comonicon, that can take a Julia project and generate a Dockerfile with SimpleContainerGenerator.


For more examples see the examples folder.

Useful Packages

Some packages that you may find useful to pair with Bonsai.

Used By Packages

No packages found.