Creating an API

REST APIs provide a structured, standardized way to expose and access data and functionalities over the internet, making it easier to integrate different software systems. REST (Representational State Transfer) means that the server does not store any state about the client session. Each request is independent from previous ones.

Creating an API with Genie Framework is as easy as adding a set of endpoints linked to a specific functionality. Moreover, it is possible to automatically generate an API documentation page with Swagger.

API endpoints

An API is comprised of multiple endpoints, each of which requires:

  • A route that defines the URL path, parameters, handler, and HTTP method to access a resource.
route("/api/hello/:name", greet, method=GET)
  • A handler function that processes the request and returns a response
function greet()
    "Hello $(params(:name))"
end

Any information to be sent to the API is passed as a parameter in the URL path (GET request) or in the body (POST request) of the request. This can be then extracted by the handler with the params call.

Continuing with the statistical analysis app in the Your first app example, suppose you want the app to return a vector of random numbers of length N at /numbers/:N. First, add an api_numbers function to the controller:

AnalysisController.jl
using GenieFramework.Genie.Renderers.Json: json
function api_numbers()
    json("x" => gen_numbers(payload(:N))))
end

It is convenient to format the response as a JSON dictionary to make it easier to consume by third parties.

Then, add a route for the endpoint in app.jl:

app.jl
route("/api/numbers/:N::Int", AnalysisController.api_numbers, method=GET)

Notice that it is also possible to specify the type of the parameter in the URL with the usual ::Type syntax.

To check that the endpoint is working, simply open a browser at /api/numbers/<N-value>.

Documenting the API

It is often a good idea to add a documentation page to make the API endpoints discoverable and easier to use. You can use the SwaggUI.jl and SwaggerMarkdown packages to individually document each endpoint and automatically generate a documentation page.

First, use the @swagger macro to add a docstring to a route with the endpoint specification following the OpenAPI format:

app.jl
using SwagUI, SwaggerMarkdown

@swagger """
/api/predict/{id}:
  get:
    description: Predict the MEDV of a house.
    parameters:
      - in: path
        name: N
        required: true
        description: Length of the random number vector.
        schema:
           type: integer
    responses:
      '200':
        description: OK
"""
route("/numbers/:N::Int", AnalysisController.api_numbers, method=GET)

Second, add a handler that builds the documentation page:

AnalysisController.jl
function api_docs()
    info = Dict{String,Any}()
    info["title"] = "Statistic analysis API"
    info["version"] = "1.0.5"
    openApi = OpenAPI("3.0", info)
    swagger_document = build(openApi)

    render_swagger(swagger_document)
end

Finally, add a route to the documentation page:

app.jl
route("/api/docs", api_docs)