building rest api without coding
TRANSCRIPT
POSTGRES-
OPENRESTY
BUILDING REST API WITHOUT
PROGRAMMING
AUTHOR
Nur Agus Suryoko
PT. Virkea Empressa Sistema /
Infrastructure Architect
Living in shells from 2005; getting paid for
it from 2009
@berandajiwa
SETUP
BUILD OPENRESTY
Download openresty from: https://openresty.org/
Extract: tar -xzvf ngx_openresty-1.9.3.1.tar.gz
Configure: ./configure --with-cc-opt=“-I/usr/include”
Make: make -j 4
Install: make install
It will install at /usr/local/openresty with its own-built nginx
binary
DIRECTORIES
/usr/local/openresty the openresty home dir
/usr/local/openresty/bin resty binary
/usr/local/openresty/nginx/sbin nginx binary
/usr/local/openresty/nginx/conf nginx conf
GET POSTGRES
READY
You can choose any postgres binary, but my favorite is from
EnterpriseDB: http://www.enterprisedb.com/products-services-
training/pgdownload
Because it already include following contrib modules:
- uuid-ossp
- pgcrypto
DDL
drop table if exists posts;
create table posts (
id uuid DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
text varchar(255) not null,
timestamp timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
user_id uuid REFERENCES users (id) NOT NULL,
tag JSON,
location point,
yes_count numeric(18,0),
no_count numeric(18,0)
);
drop table if exists users;
create table users (
id uuid DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
username varchar(255) UNIQUE NOT NULL,
email varchar(255) NOT NULL,
photo varchar(255),
location point,
registration_date timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
internal_status varchar(40) NOT NULL,
short_desc text,
password text NOT NULL,
salt text,
password_status varchar(40) NOT NULL,
password_last_changed timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
);
LET’S
START
DDL
Create the database and users:
create database ioora
Create the data structure from DDL below:
http://pastebin.com/Mi5eQyP7
NGINX.CONF
Don’t forget. The directory is: /usr/local/openresty/nginx/conf
Not the normal /etc/nginx
My complete nginx.conf: http://pastebin.com/LVsJHd6A
NGINX.CONF
Things that make it possible:
upstream database {
postgres_server 127.0.0.1 dbname=ioora user=postgres password=<your postgres password>;
}
location /posts {
postgres_pass database;
rds_json on;
postgres_query HEAD GET "SELECT * FROM posts";
postgres_query
POST "INSERT INTO posts (text, user_id) values ($arg_text, $arg_user_id)";
postgres_rewrite POST changes 201;
}
START NGINX
/usr/local/openresty/nginx/sbin/nginx
THE FIRST REST
The first REST is create a user, since no user exists in the database
curl -X POST
"http://localhost/users?username='Agus'&email='n
[email protected]'&internal_status='OK'&pas
sword='Initial1'&password_status='OK'"
It’s a bit long but please bear with it. Better if you have python installed
curl -X POST
"http://localhost/users?username='Agus'&email='n
[email protected]'&internal_status='OK'&pas
sword='Initial1'&password_status='OK'" | python
-m json.tool
THE RETURN
[
{
"email": "[email protected]",
"id": "ddaa3d39-bf27-474e-b28c-07980b3caaee",
"internal_status": "OK",
"location": null,
"password": "$2a$06$v4UTHYNPYodvVSHkhOddgu82Nbjj1VLZKncVdUcuJDn948/y.uY/G",
"password_last_changed": "2015-09-29 13:31:36.750245",
"password_status": "OK",
"photo": null,
"registration_date": "2015-09-29 13:31:36.750245",
"salt": null,
"short_desc": null,
"username": "Agus"
}
]
THE RETURN
Things to notice:
a. OpenResty echo the data that was just inserted to the
database
b. The password is encrypted by pgcrypt with bcrypt
c. The id is automatically generated uuid
d. Registration date and password_last_change fields are
automatically filled with current timestamp
Item b is defined in the SQL syntax in nginx.conf
Item c & d is defined in the postgresql data structure
IN THE DB
ioora=> \x on
Expanded display is on.
ioora=> select * from users;
-[ RECORD 1 ]---------+-------------------------------------------------------------
id | ddaa3d39-bf27-474e-b28c-07980b3caaee
username | Agus
email | [email protected]
photo |
location |
registration_date | 2015-09-29 13:31:36.750245
internal_status | OK
short_desc |
password | $2a$06$v4UTHYNPYodvVSHkhOddgu82Nbjj1VLZKncVdUcuJDn948/y.uY/G
salt |
password_status | OK
password_last_changed | 2015-09-29 13:31:36.750245
GET REST
This rest is displaying user:
curl "http://localhost/users" | python -m
json.tool
THE RETURN
[
{
"email": "[email protected]",
"id": "ddaa3d39-bf27-474e-b28c-07980b3caaee",
"internal_status": "OK",
"location": null,
"password": "$2a$06$v4UTHYNPYodvVSHkhOddgu82Nbjj1VLZKncVdUcuJDn948/y.uY/G",
"password_last_changed": "2015-09-29 13:31:36.750245",
"password_status": "OK",
"photo": null,
"registration_date": "2015-09-29 13:31:36.750245",
"salt": null,
"short_desc": null,
"username": "Agus"
}
]
Figures
THE RESTS
The other rest endpoints are stated in the nginx.conf files.
WHAT IT
CANNOT DO (AT LEAST CURRENTLY UNKNOWN)
CANNOT DO
Multiple SQL
We want to generate a salt, store that salt to a row, and then generate password from that salt. We can’t do that yet, unless we are using PL/PGSQL which I think kinda last resort.
Error return
The REST will return error-500 for any database error. Don’t know how to pass through error message from postgres to nginx
Authentication
The PostgreSQL username/password is hardcoded in nginx.conf. Dynamic username/password is not yet handled.
WHAT IT
GREAT AT (AT LEAST THEORITICALLY)
GREAT AT
Speed
No backend, just DB. That means extremely lightweight and
faaassst!
No coding
Even people without coding skill like me can create REST API.
What a bless!
BY THE
WAY…
WE ARE HIRING
Senior Ruby Developer
http://id.jobsdb.com/id/en/job/ruby-on-rails-senior-developer-
200003001503577?sr=1
Check out our Joel’s Test
Or directly sent your CV to: