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 pur­pose — 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.

One thought on “Building a microservice in Perl, part 1: Designing the API

Comments are closed.