Building a microservice in Perl, part 1: Designing the API

A microser­vice can be thought of as the dis­trib­uted com­put­ing imple­men­ta­tion of the Unix phi­los­o­phy of Do one thing and do it well.” Usually mod­eled around spe­cif­ic busi­ness domains, a well-​designed set of microser­vices each have their own life­cy­cle and com­mu­ni­cate with each oth­er and with con­sum­ing appli­ca­tions via technology-​agnostic pro­to­cols like HTTP.

Because of this, a microser­vice may be imple­ment­ed using what­ev­er is the best pro­gram­ming lan­guage, data­base, or anoth­er envi­ron­ment to fit the job. Perl can be an excel­lent choice for devel­op­ment because of its strengths as a battle-​tested, expres­sive multi-​paradigm lan­guage with a broad open-​source library of mod­ules.

In this series of arti­cles, we’ll be using Perl, the Mojolicious web frame­work, and the OpenAPI (for­mer­ly Swagger) spec­i­fi­ca­tion for describ­ing web ser­vices to devel­op an exam­ple microser­vice that adheres to the REST archi­tec­tur­al style for com­mu­ni­ca­tion over HTTP. Some knowl­edge of Perl and web devel­op­ment is assumed, and we’ll be link­ing to sup­port­ing doc­u­men­ta­tion and lit­er­a­ture as we go.

In a full microser­vices imple­men­ta­tion, we would start by mod­el­ing the busi­ness domains being ser­viced and the explic­it bound­aries between them. For the pur­pos­es of this series, we are lim­it­ing our­selves to devel­op­ing only one microser­vice with a triv­ial purpose—a toy, if you will. This ser­vice will act as a sim­ple dic­tio­nary allow­ing con­sumers to both query for the def­i­n­i­tions of words as well as add new entries.

We could envi­sion a vari­ety of con­sumers: a web front-​end, a mobile app, maybe even SMS text mes­sag­ing. The key is that the design of our appli­ca­tion pro­gram­ming inter­face (API) should not dic­tate the imple­men­ta­tion or life­cy­cle of any of these con­sumers, and it should be easy for their devel­op­ers to under­stand its specification.

To that end, we turn to OpenAPI, which gives both our microser­vice and its con­sumers an unam­bigu­ous machine-​readable descrip­tion of the inter­face with­out the need for addi­tion­al code or doc­u­men­ta­tion. And as we’ll see lat­er, we’ll use that very same spec­i­fi­ca­tion to dri­ve our web frame­work to pro­duce HTTP routes that accept valid input and pro­duce valid output.

A full OpenAPI doc­u­ment can be writ­ten in either JSON or YAML for­mat, but it must ulti­mate­ly be able to be rep­re­sent­ed in both for­mats, so there are some lim­i­ta­tions described in the spec. Here’s the OpenAPI doc­u­ment for our dic­tio­nary microser­vice in YAML:

openapi: 3.0.3
info:
  title: Dictionary
  description: The PhoenixTrap.com dictionary microservice
  version: 1.0.0
  license:
    name: Artistic License 2.0
    url: https://www.perlfoundation.org/artistic-license-20.html
paths:
  /health:
    get:
      summary: Check if this service is online
      x-mojo-to: monitoring#heartbeat
      responses:
        200:
          description: All systems operational
          content:
            application/json:
              schema:
                type: object
        500:
          description: Something is wrong
  /word/{word}:
    get:
      summary: Get the definition of a word
      x-mojo-to: word#define
      parameters:
      - $ref: '#/components/parameters/word'
      responses:
        200:
          description: Found word
          content:
            application/json:
              schema:
                type: string
        404:
          description: Could not find word
    post:
      summary: Add or replace the definition of a word
      x-mojo-to: word#save
      parameters:
      - $ref: '#/components/parameters/word'
      requestBody:
        description: Definition of a word
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                definition:
                  type: string
      responses:
        200:
          description: Word saved
    delete:
      summary: Delete an entry from the dictionary
      x-mojo-to: word#remove
      parameters:
      - $ref: '#/components/parameters/word'
      responses:
        200:
          description: Word deleted
components:
  parameters:
    word:
      description: A word in the dictionary
      in: path
      name: word
      required: true
      schema:
        type: string

(I worked on this in the free online Swagger Editor, which checks your syn­tax, pre­views what API doc­u­men­ta­tion might look like, and offers sug­ges­tions if it finds errors in your document.)

Most of the above should be fair­ly self-​explanatory to any web devel­op­er, and you can check the OpenAPI spec­i­fi­ca­tion for required and option­al fields and their allowed val­ues. The only odd field list­ed is x-mojo-to; we’ll be using the Mojolicious::Plugin::OpenAPI mod­ule to read that field when gen­er­at­ing routes to con­trollers in the Mojolicious web framework.

In the next install­ment, we’ll actu­al­ly be writ­ing some Perl by build­ing our Mojo appli­ca­tion and tests.


Discover more from The Phoenix Trap

Subscribe to get the latest posts sent to your email.

Mark Gardner Avatar

Hi, I’m Mark.

Hi, I’m Mark Gard­ner, and this is my personal blog. I show software developers how to level up by building production-ready things that work. Clear code, real projects, lessons learned.

Comments

One response to “Building a microservice in Perl, part 1: Designing the API

  1. […] part 1 we designed our API using OpenAPI/​Swagger. Now it’s time to write some tests and wire it up using […]

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)