Building Web Apps in Julia

Julia unlike Python or Go Lang does not have a lot of packages for building web applications. In Python, there are several popular battle tested web frameworks for building web applications such as Django, Flask, FastAPI, Tornado, Bottle, CherryPy, Streamlit, etc. Golang also has several packages for web programming. However in Julia we have a few such as

  • GenieFramework
  • Mux.jl
  • Merly.jl
  • HTTP.jl

GenieFramework is the most popular and it has a similar approach like Django with an MVT or MVC approach. Genie great documentation. However in this tutorial we will be using Oxygen.jl – a web framework similar to Flask and easy to use.

Just as Genie.jl is to Django , in a way Oxygen.jl is to Flask

Getting Started with Oxygen.jl

In this post, we will build a simple application using Oxygen.jl and HTTP.jl. Since Oxygen.jl is still relatively new (circa 2023), it has not a lot of features yet, however we can still build some cool things with it and contribute to it.

First, let us create a virtual environment to work in and then install our necessary packages. Below is the packages and their purpose

  • HTTP.jl : for working with HTTP request and response in Julia (similar to Request in Python)
  • Oxygen.jl: as our web framework
  • Mustache.jl: for our templating (similar to Jinja Templating in Python)
# Create our directory
mkdir web_app
cd web_app

Install Packages

# Activate virtualenv
activate .
add HTTP Oxygen Mustache

Next we will create a file app.jl where our backend code will be. Let us create a basic app with Oxygen.jl

using Oxygen
using HTTP 

# creating route
@get "/" function(req::HTTP.Request)
    return "Hello Julia Web App"
end 

# Serialize dict to json 
@get "/home" function(req::HTTP.Request)
    return Dict("name" => "Jesse")
end 

serve(port=8001)

We can now start our app using the code below, the –project will activate and use the packages in our virtual environment instead .

julia --project app.jl

You can check it out inside your browser to see the web app

Oxygen automatically generate a swagger UI on 127.0.0.1:80017docs for all the routes created, which can be useful when building REST APIs

We can also render html and work with other features such as

  • Query Params
  • Path Params
  • Render HTML
  • Serializing JSON
  • etc

Below is the entire code

using Oxygen
using HTTP 
using Mustache



function render_html(html_file::String, context::Dict = Dict();status=200, headers=["Content-Type" => "text/html; charset=utf-8"]) :: HTTP.Response
    is_context_empty = isempty(context) === true 
    # return raw hmtl without context 
    if is_context_empty
        io = open(html_file,"r") do file 
            read(file, String)
        end
        template = io |> String 
    else 
        # Render html with context 
        io = open(html_file,"r") do file 
            read(file, String)
        end
        template = String(Mustache.render(io, context))
    end 
        return HTTP.Response(status, headers,body = template)
end 

    
# creating route
@get "/" function(req::HTTP.Request)
    return "Hello Julia Web App"
end 

# Serialize dict to json 
@get "/home" function(req::HTTP.Request)
    return Dict("name" => "Jesse")
end 

# Render HTML 
# @get "/generate" function(req::HTTP.Request)
#     render_html("index.html")
# end


# Render HTML  with context
@get "/generate" function(req::HTTP.Request)
    context = Dict("name" => "Jesse")
    return render_html("index.html", context)
end

# Receiving query params
# http://127.0.0.1:8001/query?books=bible
@get "/query" function(req::HTTP.Request)
    return queryparams(req)
end 


# Receiving form data 
@get "/generate/password" function(req::HTTP.Request)
    form_data = queryparams(req)
    fname = get(form_data,"fname","")
    context = Dict("fname" => fname)
    return render_html("generate.html", context)
end 


# path params 
# http://127.0.0.1:8001/{num1}/{num2}
@get "/add/{num1}/{num2}" function(req::HTTP.Request, num1::Float64, num2:: Float64)
    return num1 + num2
end 

# Routes : HOF for reuse 
api = router("/api", tags=["api endpoint"])

@get api("/add/{num1}/{num2}") function(req::HTTP.Request, num1::Float64, num2:: Float64)
    return num1 + num2
end 

@post api("/multiply/{num1}/{num2}") function(req::HTTP.Request, num1::Float64, num2:: Float64)
    return num1 * num2
end 


serve(port=8001)

You can also check this video tutorial for more

Thank You for your Attention

Jesus Saves

By Jesse E. Agbe(JCharis)

Leave a Comment

Your email address will not be published. Required fields are marked *