Path Parameters

You can declare path "parameters" or "variables" inside your route with braces and those values are passed directly to your request handler.

@get "/multiply/{a}/{b}" function(req, a::Float64, b::Float64)
    return a * b
end

The values of {a} & {b} in the path will get passed to the request handler with the parameter with the same name.

Path parameters with types

You can declare the type of a path parameter in the function, using standard Julia type annotations

Let's take a look back at our first example above we have code to add two numbers.

@get "/multiply/{a}/{b}" function(req, a::Float64, b::Float64)

In this line we have our request type, route, and function handler defined. Looking closer at our request handler, we can see our variables have type annotations attached to them.

Oxygen will use any type annotations you give it to try to convert the incoming data into that type. Granted, these are completely optional, if you leave out the type annotation then Oxygen will assume it's a string by default. Below is another way to write the same function without type annotations.

@get "/multiply/{a}/{b}" function(req, a, b)
    return parse(Float64, a) * parse(Float64, b)
end

Autogenerated Docs & Path Types

And when you open your browser at http://127.0.0.1:8080/docs, you will see the autogenerated interactive documentation for your api.

If type annotations were provided in the request handler, they will be taken into account when generating the openapi spec. This means that the generated documentation will know what the input types will be and will not only show, but enforce those types through the interactive documentation.

Practically, this means that your users will know exactly how to call your endpoint and your inputs will always remain up to date with the code.

Additional Parameter Type Support

Oxygen supports a lot of different path parameter types outside of Julia's base primitives. More complex types & structs are automatically parsed and passed to your request handlers.

In most cases, Oxygen uses the built-in parse() function to parse incoming parameters. But when the parameter types start getting more complex (eg. Vector{Int64} or a custom struct), then Oxygen assumes the parameter is a JSON string and uses the JSON3 library to serialize the parameter into the corresponding type

using Dates
using Oxygen
using StructTypes

@enum Fruit apple=1 orange=2 kiwi=3

struct Person 
  name  :: String 
  age   :: Int8
end

# Add a supporting struct types
StructTypes.StructType(::Type{Person}) = StructTypes.Struct()
StructTypes.StructType(::Type{Complex{Float64}}) = StructTypes.Struct()

@get "/fruit/{fruit}" function(req, fruit::Fruit)
  return fruit
end

@get "/date/{date}" function(req, date::Date)
  return date
end

@get "/datetime/{datetime}" function(req, datetime::DateTime)
  return datetime
end

@get "/complex/{complex}" function(req, complex::Complex{Float64})
  return complex
end

@get "/list/{list}" function(req, list::Vector{Float32})
    return list
end

@get "/data/{dict}" function(req, dict::Dict{String, Any})
  return dict
end

@get "/tuple/{tuple}" function(req, tuple::Tuple{String, String})
  return tuple
end

@get "/union/{value}" function(req, value::Union{Bool, String, Float64})
  return value
end

@get "/boolean/{bool}" function(req, bool::Bool)
  return bool
end

@get "/struct/{person}" function(req, person::Person)
  return person
end

@get "/float/{float}" function (req, float::Float32)
  return float
end

serve()