Building a microservice in Perl, part 1: Designing the API
Tags: perl, microservices, mojolicious, openapi
Published: 2021-02-27 22:13:16

---
title: Building a microservice in Perl, part 1: Designing the API
published: true
date: 2021-02-27 22:09:59 UTC
tags: Perl,microservice,Mojolicious,OpenAPI
canonical_url: https://phoenixtrap.com/2021/02/27/perl-microservice-part-1/?utm_source=rss&utm_medium=rss&utm_campaign=perl-microservice-part-1
series: Building a microservice in Perl
---

A microservice can be thought of as the distributed computing implementation of the [Unix philosophy](http://catb.org/~esr/writings/taoup/html/ch01s06.html) of **“Do one thing and do it well.**” Usually modeled around specific business domains, a well-designed set of microservices each have their own lifecycle and communicate with each other and with consuming applications via technology-agnostic protocols like [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol).  
  
Because of this, a microservice may be implemented using whatever is the best programming language, database, or other environment to fit the job. **[Perl](https://www.perl.org/) can be an excellent choice for development** because of its strengths as a battle-tested, expressive multi-paradigm language with a [broad open-source library of modules](https://www.perl.org/cpan.html).

In this series of articles, we’ll be using Perl, the [Mojolicious](https://mojolicious.org/) web framework, and the [OpenAPI](https://swagger.io/specification/) (formerly [Swagger](https://swagger.io/)) specification for describing web services to develop an example microservice that adheres to the [REST](https://restfulapi.net/) architectural style for communication over HTTP. Some knowledge of Perl and web development is assumed, and we’ll be linking to supporting documentation and literature as we go.

In a full microservices implementation, we would start by **modeling the business domains being serviced and the explicit boundaries between them.** For the purposes of this series, we are limiting ourselves to developing only one microservice with a trivial purpose—a toy, if you will. This service will act as a simple dictionary allowing consumers to both query for the definitions of words as well as add new entries.

We could envision a variety of consumers: a web front-end, a mobile app, maybe even SMS text messaging. The key is that **the design of our application programming interface (API) should not dictate the implementation or lifecycle** of any of these consumers, and it should be easy for their developers to understand its specification.

To that end, we turn to [OpenAPI](https://spec.openapis.org/oas/v3.0.3.html), which gives both our microservice and its consumers **an unambiguous machine-readable description of the interface** without the need for additional code or documentation. And as we’ll see later, we’ll use that very same specification to drive our web framework to produce HTTP routes that accept valid input and produce valid output.

A full OpenAPI document can be written in either JSON or YAML format, but it must ultimately be able to be represented in both formats, so there are some [limitations described in the spec](https://spec.openapis.org/oas/v3.0.3.html#format). Here’s the OpenAPI document for our dictionary microservice in YAML:

```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](https://editor.swagger.io/)**, which checks your syntax, previews what API documentation might look like, and offers suggestions if it finds errors in your document.)

Most of the above should be fairly self-explanatory to any web developer, and you can check [the OpenAPI specification](https://spec.openapis.org/oas/v3.0.3.html) for required and optional fields and their allowed values. The only odd field listed is `x-mojo-to`; we’ll be using the [Mojolicious::Plugin::OpenAPI](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI) module to read that field when generating routes to controllers in the [Mojolicious](https://mojolicious.org/) web framework.

In the next installment, we’ll actually be writing some Perl by building our Mojo application and tests.