REST API with Nginx only

How to build a simple REST API using only Nginx and PostgreSQL

Sometimes it’s overkill to use a web framework if you only need to develop a very simple REST API. It turns out that Nginx can be used to develop a full fledged REST API and PostgreSQL can easily be used for persistence, or any other SQL or NoSQL database.

I’m going to show you how to create a simple CRUD API for articles.

Create the database

CREATE DATABASE articledb WITH OWNER username ENCODING 'UTF8';

CREATE TABLE articles (
    id serial PRIMARY KEY,
    title varchar(50) NOT NULL,
    body varchar(32000) NOT NULL,
    created_at timestamp DEFAULT current_timestamp
);


INSERT INTO articles (title, body) VALUES ('Test title 1', 'Test body 1');
INSERT INTO articles (title, body) VALUES ('Test title 2', 'Test body 2');
INSERT INTO articles (title, body) VALUES ('Test title 3', 'Test body 3');

The complete nginx.conf

worker_processes 8;

events {}

http {
  upstream database {
    postgres_server 127.0.0.1 dbname=articledb user=username password=yourpass;
  }

  server {
    listen       8080;
    server_name  localhost;

    location /articles {
      postgres_pass database;
      rds_json on;
      postgres_query    HEAD GET  "SELECT * FROM articles";

      postgres_escape $title $arg_title;
      postgres_escape $body  $arg_body;
      postgres_query
        POST "INSERT INTO articles (title, body) VALUES($title, $body) RETURNING *";
      postgres_rewrite  POST changes 201;
    }

    location ~ /articles/(?<id>\d+) {
      postgres_pass database;
      rds_json  on;
      postgres_escape $escaped_id $id;
      postgres_query    HEAD GET  "SELECT * FROM articles WHERE id=$escaped_id";
      postgres_rewrite  HEAD GET  no_rows 410;

      postgres_escape $title $arg_title;
      postgres_escape $body  $arg_body;
      postgres_query
        PUT "UPDATE articles SET title=$title, body=$body WHERE id=$escaped_id RETURNING *";
      postgres_rewrite  PUT no_changes 410;

      postgres_query    DELETE  "DELETE FROM articles WHERE id=$escaped_id";
      postgres_rewrite  DELETE  no_changes 410;
      postgres_rewrite  DELETE  changes 204;
    }
  }
}

API client test

Get all articles:

curl http://localhost:8080/articles

Create a new article:

curl -X POST http://localhost:8080/articles?title=Article1&body=body1    

Update article:

curl -X PUT http://localhost:8080/articles/1?title=Article2&body=body2

Delete article:

curl -X DELETE http://localhost:8080/articles/1