COBOL is 60. Let's give it a REST framework for its birthday

Mar 26, 2019

PART ONE

1959 - “Mack the Knife”, as sung by Frank Sinatra, was top of the charts. Harold Macmillan’s Conservatives had just beaten Hugh Gaitskell and Labour in the British Parliamentary elections, as the Austin Motor Company released the first Morris Mini-Minor. And in the United States, the Committee on Data Systems Languages released COBOL, which was partially based on the work of Grace Hopper.

The first COBOL program ran on an RCA 501, a transistor-based computer, which supported punched cards, but not silicon chips, because they weren’t commercially available yet.

COBOL’s an interesting language. It retains a lot of features which are intrinsically linked to the physical structure of early (and some modern computers). We don’t have long to talk about it. But it has a lot of features which you won’t have come across if you haven’t written anything in it, and some of them are worth exploring and might give you ideas for improvements to your own code once you’ve used it. It also has some frustrating features, like a complete lack of proper functions.

So, happy 60th birthday COBOL. And what better way to celebrate a 60th birthday than with a present. I thought I’d give COBOL a REST framework for its birthday.

I’m going to use GnuCOBOL. There are a few options at this point. There is code for handling ports available, but it’s more complicated, and to be frank, I don’t have long for this one. Instead I’ll use same basic code for reading environment variables, and make use of the cgi-bin interface in Apache. There’s an example online.

Here’s a COBOL “Hello World”, for the uninitiated:

identification division.
program-id. hello.

procedure division.
display "Hello World".
stop run.

And here’s how one of these might look in an earlier version of the language. Note the we now have access to lower case.

COBOL

So, we can write a straightforward program and get a webpage, if we drop the file into cgi-bin somewhere in its compiled form:

identification division.
program-id. cobolapi.

data division.

working-storage section.
01 newline              pic x     value x'0a'.

procedure division.

display
   "Content-type: text/html"
   newline
   Hello World
end-display

end program cobolapi.

Simple. At this point, we want to serve this up. I recommend getting a simple docker image for Apache, and writing a simple Docker script to compile the COBOL on it. You’ll want one based on Ubuntu, for example (rather than Alpine), as you’ll want to be able to apt-get install the cobol compiler. Check out my repo for inspiration: https://gitlab.com/bencollier/cobol-api/.

So to turn this into something more closely resembling a REST API, we need a few things. Firstly, we want it serving up JSON. Fairly simple, just change the Content-Type to “application/json” and return JSON. Secondly, we want to be able to serve up dynamic content, which is nice and easy thanks to COBOL’s subprogram feature, and thirdly, we want a decent router, which will parse URLs and send contextual information to individual functions.

Unfortunately for us, COBOL doesn’t support regular expressions of the form that you might be used to from Flask or Express. The best I can do at short notice is the wonderfully-named “Unstring” directive, which basically explodes strings around a delimiter:

unstring value-string
delimited by "/"
into
  leader delimiter D0 count C0
  api delimiter D1 count C1
  person delimiter D2 count C2
  person-id delimiter D3 count C3
end-unstring

if person is equal to "people"
    call "person" using by reference person-id.
if value-string is equal to "/api"
    call "root".
if value-string is equal to "/api/towns"
    call "towns".

The first block of code here breaks out our path, and the second, chooses where to go based on what’s in it.

We can drop this code right in where the “Hello World” was previously in our program, and thanks to the fact that we’re using cgi-bin, any subprogram that we call doesn’t need to even be aware of the internet. We can set it to display what we like and we’ll get it outputted in the user’s browser.