Wrapper opportunity

When using a web API it can be nice to have a wrapper around the various HTTP requests that can be made.

On the plus side, this allows for a separation of concerns. Your code doesn't need to get into the details of making the HTTP requests.

Often, the provider of the web API also supplies wrappers for various popular programming languages. Some, like TMDb (used in the previous post) accept wrappers from their developers and list them for use by other developers.

There is also a downside. Writing a wrapper for an API that has dozens of requests, each with several options, can be tedious. You also ought to write documentation for it. The web API provider almost always provides Open API documentation for their requests, but that doesn't cover your wrapper.

Writing a ruleset to be used as a wrapper

The example from the previous post used only one HTTP request from the TMDb API, the one to get the list of movie genres.

We can wrap that in a function, provided by a ruleset to be used as a module.

ruleset org.themoviedb.sdk {
  meta {
    provides genre_movie_list
  }
  global {
    api_key = ctx:rid_config{"api_key"}
    genre_movie_list = function() {
      the_url = "https://api.themoviedb.org/3/genre/movie/list?api_key="
      response = http:get(the_url+api_key)
      response.get("content").decode().get("genres")
    }
  }
}

In writing this, we chose a couple of identifiers, and it's worth looking at each of these.

What to name the ruleset?

We chose org.themoviedb.sdk as the ruleset identifier. This name, strictly speaking, would "belong to" TMDb because they control the domain name themoviedb.org.

We felt justified in using one of their names because, first of all, it is very unlikely that they would write a KRL wrapper, and, second of all, we might at some point complete it and contribute it to them.

What to name the provided function?

We chose genre_movie_list to sort of mirror the path of the HTTP GET request that it performs. We didn't put "get" in the name because we'll use functions for GET requests and defined actions for POST and DELETE requests as we flesh out the wrapper.

The wrapper will need to be configured

Notice that it obtains the API key from the ruleset configuration, using the second technique that we showed in the previous post.

Although we haven't shown the corresponding changes to our application ruleset yet, we can show here what the Rulesets tab of the developer UI will look like:


You can see that our application ruleset, my.movies.app, is installed in this pico, along with two modules that it will use: html and org.themoviedb.sdk. The latter, the wrapper we have been discussing, has been configured with our private API key.

Using the wrapper ruleset as a module

Our application ruleset will need to declare its use of the wrapper ruleset in its meta block, specifying the identifier tmdb as its alias:

ruleset my.movies.app {
  meta {
    name "movies"
    use module io.picolabs.wrangler alias wrangler
    use module html
    use module org.themoviedb.sdk alias tmdb
    shares genres
  }
  ...
}

Because the wrapper provides the function genre_movie_list, we can use it in a rule that selects when we install our application ruleset in our pico.

We do this in a new rule that selects when our application ruleset is installed in the pico:

  rule getMovieGenres {
    select when my_movies_app factory_reset
    fired {
      ent:genres := tmdb:genre_movie_list()
      raise my_movies_app event "new_genres" attributes event:attrs
    }
  }

We chose to assign the genre list to the same entity variable that we used before, ent:genres, so no other changes will be needed in our application ruleset.

Complete rulesets

The complete wrapper ruleset, to be used as a module, can be installed from here. Be sure to configure your own API key as you do the installation.

The complete application ruleset which implements this technique can be found here.

Multitenancy in a web application

In the previous section, by saying "your own API key", we are indicating that although both your pico and mine have the exact same rulesets installed, they are independent of each other.

With other software stacks, achieving multitenancy can be quite complex and costly. With picos, you get it for free.


No comments:

Post a Comment