SkillAgentSearch skills...

Oxygen.jl

πŸ’¨ A breath of fresh air for programming web apps in Julia

Install / Use

/learn @OxygenFramework/Oxygen.jl
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Oxygen.jl

<!-- START HTML --> <div> </br> <p align="center"><img src="oxygen.png" width="20%"></p> <p align="center"> <strong>A breath of fresh air for programming web apps in Julia.</strong> </p> <p align="center"> <a href='https://juliahub.com/ui/Packages/General/Oxygen'><img src='https://juliahub.com/docs/General/Oxygen/stable/version.svg' alt='Version' /></a> <a href='https://oxygenframework.github.io/Oxygen.jl/stable/'><img src='https://img.shields.io/badge/docs-stable-blue.svg' alt='documentation stable' /></a> <a href='https://github.com/OxygenFramework/Oxygen.jl/actions/workflows/ci.yml'><img src='https://github.com/OxygenFramework/Oxygen.jl/actions/workflows/ci.yml/badge.svg' alt='Build Status' /></a> <a href='https://coveralls.io/github/OxygenFramework/Oxygen.jl?branch=master'><img src='https://coveralls.io/repos/github/OxygenFramework/Oxygen.jl/badge.svg?branch=master' alt='Coverage Status' /></a> <!-- <a href='https://codecov.io/gh/OxygenFramework/Oxygen.jl'><img src='https://codecov.io/gh/OxygenFramework/Oxygen.jl/branch/master/graph/badge.svg' alt='Coverage Status' /></a> --> </p> </div> <!-- END HTML -->

About

Oxygen is a micro-framework built on top of the HTTP.jl library. Breathe easy knowing you can quickly spin up a web server with abstractions you're already familiar with.

Contact

Need Help? Feel free to reach out on our social media channels.

Chat on Discord Discuss on GitHub

Features

  • Straightforward routing
  • Real-time Metrics Dashboard
  • Auto-generated swagger documentation
  • Out-of-the-box JSON serialization & deserialization (customizable)
  • Type definition support for path parameters
  • Request Extractors
  • Application Context
  • Multiple Instance Support
  • Multithreading support
  • Websockets, Streaming, and Server-Sent Events
  • Cron Scheduling (on endpoints & functions)
  • Middleware chaining (at the application, router, and route levels)
  • Prebuilt Middleware (RateLimiter, Cors, BearerAuth)
  • Static & Dynamic file hosting
  • Hot reloads with Revise.jl
  • Templating Support
  • Plotting Support
  • Protocol Buffer Support
  • Route tagging
  • Repeat tasks

Installation

pkg> add Oxygen

Minimalistic Example

Create a web-server with very few lines of code

using Oxygen
using HTTP

@get "/greet" function(req::HTTP.Request)
    return "hello world!"
end

# start the web server
serve()

Handlers

Handlers are used to connect your code to the server in a clean & straightforward way. They assign a url to a function and invoke the function when an incoming request matches that url.

  • Handlers can be imported from other modules and distributed across multiple files for better organization and modularity
  • All handlers have equivalent macro & function implementations and support do..end block syntax
  • The type of first argument is used to identify what kind of handler is being registered
  • This package assumes it's a Request handler by default when no type information is provided

There are 3 types of supported handlers:

  • Request Handlers
  • Stream Handlers
  • Websocket Handlers
using HTTP
using Oxygen

# Request Handler
@get "/" function(req::HTTP.Request)
    ...
end

# Stream Handler
@stream "/stream" function(stream::HTTP.Stream)
    ...
end

# Websocket Handler
@websocket "/ws" function(ws::HTTP.WebSocket)
    ...
end

They are just functions which means there are many ways that they can be expressed and defined. Below is an example of several different ways you can express and assign a Request handler.

@get "/greet" function()
    "hello world!"
end

@get("/gruessen") do 
    "Hallo Welt!"
end

@get "/saluer" () -> begin
    "Bonjour le monde!"
end

@get "/saludar" () -> "Β‘Hola Mundo!"
@get "/salutare" f() = "ciao mondo!"

# This function can be declared in another module
function subtract(req, a::Float64, b::Float64)
  return a - b
end

# register foreign request handlers like this
@get "/subtract/{a}/{b}" subtract
<details> <summary><b>More Handler Docs</b></summary>

Request Handlers

Request handlers are used to handle HTTP requests. They are defined using macros or their function equivalents, and accept a HTTP.Request object as the first argument. These handlers support both function and do-block syntax.

  • The default Handler when no type information is provided
  • Routing Macros: @get, @post, @put, @patch, @delete, @route
  • Routing Functions: get(), post(), put(), patch(), delete(), route()

Stream Handlers

Stream handlers are used to stream data. They are defined using the @stream macro or the stream() function and accept a HTTP.Stream object as the first argument. These handlers support both function and do-block syntax.

  • @stream and stream() don't require a type definition on the first argument, they assume it's a stream.
  • Stream handlers can be assigned with standard routing macros & functions: @get, @post, etc
  • You need to explicitly include the type definition so Oxygen can identify this as a Stream handler

Websocket Handlers

Websocket handlers are used to handle websocket connections. They are defined using the @websocket macro or the websocket() function and accept a HTTP.WebSocket object as the first argument. These handlers support both function and do-block syntax.

  • @websocket and websocket() don't require a type definition on the first argument, they assume it's a websocket.
  • Websocket handlers can also be assigned with the @get macro or get() function, because the websocket protocol requires a GET request to initiate the handshake.
  • You need to explicitly include the type definition so Oxygen can identify this as a Websocket handler
</details>

Routing Macro & Function Syntax

There are two primary ways to register your request handlers: the standard routing macros or the routing functions which utilize the do-block syntax.

For each routing macro, we now have a an equivalent routing function

@get    -> get()
@post   -> post()
@put    -> put()
@patch  -> patch()
@delete -> delete()
@route  -> route()

The only practical difference between the two is that the routing macros are called during the precompilation stage, whereas the routing functions are only called when invoked. (The routing macros call the routing functions under the hood)

# Routing Macro syntax
@get "/add/{x}/{y}" function(request::HTTP.Request, x::Int, y::Int)
    x + y
end

# Routing Function syntax
get("/add/{x}/{y}") do request::HTTP.Request, x::Int, y::Int
    x + y
end

Render Functions

Oxygen, by default, automatically identifies the Content-Type of the return value from a request handler when building a Response. This default functionality is quite useful, but it does have an impact on performance. In situations where the return type is known, It's recommended to use one of the pre-existing render functions to speed things up.

Here's a list of the currently supported render functions: html, text, json, file, xml, js, css, binary

Below is an example of how to use these functions:

using Oxygen 

get("/html") do 
    html("<h1>Hello World</h1>")
end

get("/text") do 
    text("Hello World")
end

get("/json") do 
    json(Dict("message" => "Hello World"))
end

serve()

In most cases, these functions accept plain strings as inputs. The only exceptions are the binary function, which accepts a Vector{UInt8}, and the json function which accepts any serializable type.

  • Each render function accepts a status and custom headers.
  • The Content-Type and Content-Length headers are automatically set by these render functions

Path parameters

Path parameters are declared with braces and are passed directly to your request handler.

using Oxygen

# use path params without type definitions (defaults to Strings)
@get "/add/{a}/{b}" function(req, a, b)
    return parse(Float64, a) + parse(Float64, b)
end

# use path params with type definitions (they are automatically converted)
@get "/multiply/{a}/{b}" function(req, a::Float64, b::Float64)
    return a * b
end

# The order of the parameters doesn't matter (just the name matters)
@get "/subtract/{a}/{b}" function(req, b::Int64, a::Int64)
    return a - b
end

# start the web server
serve()

Query parameters

Query parameters can be declared directly inside of your handlers signature. Any parameter that isn't mentioned inside the route path is assumed to be a query parameter.

  • If a default value is not provided, it's assumed to be a required parameter
@get "/query" function(req::HTTP.Request, a::Int, message::String="hello world")
    return (a, message)
end

Alternatively, you can use the queryparams() function to extract the raw values from the url as a dictionary.

@get "/query" function(req::HTTP.Request)
    return queryparams(req)
end

HTML Forms

Use the formdata() function to extract and parse the form data from the body of a request. This function returns a dictionary of key-value pairs from the form

using Oxygen

# Setup a basic form
@get "/" function()
    html("""
    <form action="/form" method="post">
        <label for="firstname">First name:</label><br>
        <input type="text" id="firstname" name="firstname"><br>
        <label for="lastname">Last name:</label><br>
        <input type="text" id="lastname" name="lastname"><br><br>
        <input type="submit" value="Submit">
    </form>
    """)
end

# Parse the form data and return it
@post "/form" function(req)
    data = formdata(req)
    return data
end

serve()

Return JSON

All objects are automatically

View on GitHub
GitHub Stars495
CategoryDevelopment
Updated5d ago
Forks35

Languages

Julia

Security Score

100/100

Audited on Mar 23, 2026

No findings