How I Encrypted, Documented, and Tested My First REST API

·

6 min read

I added a lot more to my REST API than just the JSON responses. Borum Jot was the first project I tried seriously unit testing my code, encrypting the data, and documenting my back-end. In this article, I will discuss cybersecurity, software testing, and documentation of my REST API.

Encryption

I encrypted my data using defuse/php-encryption. This library, claiming to be secure, unlike other libraries, did the encryption and decryption for me. To encrypt and decrypt, I needed my own key, which I generated by running

$ composer require defuse/php-encryption
$ vendor/bin/generate-defuse-key

Composer is a package manager for PHP applications. The key is 256 bits long and can be stored either in a file (unsecure), or in the environmental variables. Vercel has a built-in way of storing environmental variables, and was the best place, without extra tools, for me to store the key.

_Truthfully, I stored the key in a text file in the etc folder in the root directory because I didn't realize I could store it in the $_ENV at the time. This is highly insecure, so I am going to move this into a secure environmental variable soon_

Then, at each request that updated or created data that I wanted to encrypt - task and note details - I loaded the key and called the encryption function. Similarly, for each request that fetched data that I encrypted, I loaded the key and decrypted before sending the response. This way, the front-ends never had to worry about encryption or decryption because I wrote everything on the backend, once.

Documentation

To document my APIs, I got inspiration from the Stack Exchange API documentation. I used NextJS to make a static documentation site for the entire Borum ecosystem, including Borum Jot. Then, for each page, I specified the request method, request headers, query string, request body (for POST, PUT, and DELETE requests), and response body.

Here is a given page of my developer documentation website, which is live, hosted by Vercel, and open-source on GitHub:

A sample Borum Jot endpoint API reference on my Borum Dev Documentation site

A sample Borum Jot endpoint API reference on my Borum Dev Documentation site

Because I am fluent in JavaScript, I did not have any trouble setting up the documentation site. I have a JSON file with data on each endpoint that I update whenever I update the Borum Jot REST API.

I suggest including the following as a bare minimum when documenting REST or other Web API's:

  • Request Headers
  • Request Query String
  • Request Method
  • Request Body
  • Response Body

Testing

I used PHPUnit, a PHP unit-testing framework, and GuzzleHttp, a PHP HTTP client, to unit test my application. GuzzleHttp acts as a client to the REST API server, making requests and asserting information about the responses.

namespace BorumJot\Tests;

use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;

class LoginTest extends TestCase {
    private $http;

    public function setUp() : void {
        $this->http = new Client(["base_uri" => "https://api.jot.bforborum.com/api/v1/"]);
    }

    public function testPost() {
        $response = $this->http->post('login');

        $this->assertEquals(200, $response->getStatusCode());

        $contentType = $response->getHeaders()["Content-Type"][0];
        $this->assertEquals("application/json; charset=UTF-8", $contentType);
    }
}

The TestCase is a superclass in PHPUnit that indicates that the class contains test cases. The setUp() method is called by PHPUnit before each test. GuzzleHttp's Client class's "request-method methods" (like .get() and .post()) provide information on the response, such as the headers and status code as shown above.

Setting Up Unit Testing

First I had to run composer install phpunit/phpunit guzzlehttp/guzzle to install the PHPUnit and GuzzleHttp packages.

I added the following to composer.json into the top-level object.

"scripts": {
   "test": "phpunit tests"
}

This will substitute phpunit tests for composer test. It is a common practice to substitute the unit testing framework command for the package manager's command to have one command prefix to rule them all. However, this is not necessary, for you could simply run phpunit tests.

The last step is to configure phpunit to find the folder with all the unit tests. I put mine in the root directory and called it tests, but you can call it and place it anywhere you would like, except maybe in auto-generated folders.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php">
    <testsuites>
        <testsuite name="Borum Jot REST API Test Suite">
            <directory suffix=".php">./tests/</directory>
        </testsuite>
    </testsuites>
</phpunit>

Replace ./tests/ with the path to the folder with the unit tests. The test suite is an arbitrary name you give to a group of tests to identify it.

And that's how I documented, tested, and encrypted the data of my first REST API. Have you ever documented your own API? What tools did you use? Share your own projects down below!