Image copyright (c) 2022 Sergio Mijatovic \n REST (Representational State Transfer) methodology is basically a way to build web services. Much can be found on the web about it; for example, see [this article](https://www.ibm.com/cloud/learn/rest-apis). I'll talk about how to build a REST application and an API for it. \n \n The application will be about shopping: add customers and items for sale, then create, update and delete orders. So it's a simple API but it has most of the moving parts you'd need, and it should be fairly clear how to expand it. \ Here, I will explain the basics; at the end of the article is a link to a complete application. This way you'd get the essentials with very little coding, which is a great way to learn. \n \n Instead of a grand architectural diagram, I'll start the way a typical human would: by prototyping it from the ground up. \ ### Install infrastructure software \n You will need-[Apache](https://httpd.apache.org/docs/current/install.html) or [Nginx](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/) as a web server, [PostgreSQL](https://www.postgresql.org/download/) for a database, and [Vely](https://vely.dev/pkg/), as an application infrastructure. \n ### Create an application \n First I'll create an application. To that end, I will create a directory where my source code will be: \n ```bash mkdir shopping cd shopping ``` \n and then the-[Vely](https://vely.dev/)-application that I aptly named "shopping": \n ```bash sudo vf -i -u $(whoami) shopping ``` \n The "-i" option says to create an application, and "-u" that it will be owned by you (i.e. the result of "whoami", which is your current OS user). \n ### Setup a database \n Okay, so the application is created. The very first resource my REST application needs is a customer. Without being able to represent customers, there's no shopping. \n \n Create the Postgres user and the database: \n ```bash echo "create user $(whoami); create database db_shopping with owner=$(whoami); grant all on database db_shopping to $(whoami); \q " | sudo -u postgres psql ``` \n This will create a PostgreSQL user with the same name as my Linux OS user, and that's fine. It makes logging in easier and I won't need a password, because Postgres will authenticate me through my OS user session. First thing I need is to create a table for customers. Login to the database just created: \n ```bash psql -d db_shopping ``` \n and create the customers table: \n ```sql create table if not exists customers (firstName varchar(30), lastName varchar(30), customerID bigserial primary key); ``` \n It's a very simple table, with the customer's first and last name. "customerID" is an auto-generated, unique ID assigned to a customer. The database will do that for me. Once done here, press Ctrl-D to exit the database shell. \n \n To be able to use this database, I need to create a-database_config_file. Each database must have one. The database configuration file is simply the connection information, as prescribed by a given database vendor, in this case, PostgreSQL. Typically, it contains the login information and the database identification. In this case, create the configuration file named "db_shopping" (you can name it anything, but make sure to use that name going forward): \n ```bash echo "user=$(whoami) dbname=db_shopping" > db_shopping ``` \n Postgres will need my Operating System user name and the database name. Those are the same names used when I created the Postgres user and database above. \n ### Make a web service \n I can put what I have so far to good use right away. Open an editor and create the file "add_customer.vely" and copy and paste this there: \n ```clike #include "vely.h" void add_customer() { out-header use content-type "application/json" input-param first_name input-param last_name // Add a customer SQL run-query @db_shopping ="insert into customers (firstName, lastName) \ values ('%s', '%s') returning customerID" output define customerID : \ first_name, last_name @"<<p-out customerID>>" end-query } ``` \n Now, this is very simple but it does a lot. It is a typical kind of web service you'll write often. Some input parameters are provided, and some SQL executes with that data. \n \n In this case, there are two-input-parameters, "first_name" and "last_name". A database record is inserted in the "customers" table. The “customerID” created for the customer is displayed as a super simple JSON document. That's it for the web service functionality on the back end. \n ### Build an application \n How can I make use of all this so far? \ Make the application first: ```bash vv -q --db=postgres:db_shopping --path="/api/v1/shopping" ``` \n "vv -q" is the main part here, it says to generate C code from Vely source files and create a Makefile, and then make the native executable for the application. The "--db=postgres:db_shopping" says that you're using a Postgres database and it's described in the configuration file "db_shopping". Finally "--path="/api/v1/shopping"" lets you specify the URL path prefix. More on that in just a bit. \n \n I can now use the application, as basic and small as it is at the moment. I'll add to it, but this is the most important part, and everything else will be sort of replicating what I've already done. So what you've learned so far is what you really need to know. \n ### Run the application \n There are several ways I can run this. \n \n To begin with, a Vely program consists of request handlers. The function "add_customer()" I wrote is a request handler. A request handler is always in a file with the same name, so it has to be "add_customer.vely". I can write other functions in it, but I've got to have "add_customer()" in it, because Vely framework will call it when it's asked to fulfill the request "add_customer". Note the request can be "add-customer" too, because Vely will convert hyphens to underscores so they are valid C identifiers. \n \n Another thing to keep in mind, is that Vely handles HTTP requests. So regardless of how you call a Vely program, it has to be a HTTP request. That's good, because it makes the interface uniform and standard across the board. \n \n All right, knowing this, I'm ready to run the program. \n ### Run as a command-line program \n The first way to run my REST application is to simply call it as a command line program. This is useful if the program is intended to run like that, and also for debugging purposes: \n ```bash export REQUEST_METHOD=POST export SCRIPT_NAME="/api/v1/shopping" export PATH_INFO="/add-customer/first-name/Joe/last-name/Darling" export QUERY_STRING="" /var/lib/vv/bld/shopping/shopping ``` \n This is a fully fledged HTTP POST request. The request method is "POST" because a resource is created, and in this case it's a customer. The SCRIPT_NAME is set to the value I specified in "--path" option when making the application. It can be anything, but it must end with application name (recall specifying it in "vf" call when it was created). That's the application prefix. By default, it's just application name, so if you omitted "--path" then it would be just "/shopping". \n \n Next is the PATH_INFO. The first path segment is always the request name. I have created one request handler so far, so it's got be "add-customer" (or “add_customer” is just fine too). Then there are any input parameters immediately followed by their values. In this case there are two input parameters (recall "input-param" statements in your code), so "first_name" will have a value "Joe", and "last_name" will be "Darling". Remember that Vely translates hyphens into underscores in names. \n \n QUERY_STRING would have additional filters for the request, and they would be in the form of: \n ```javascript <param>=<value>&... ``` \n Those parameters are obtained in your code via the exact same "input-param" statement. In fact you could rewrite the above as: \n ```bash ... export PATH_INFO="/add-customer" export QUERY_STRING="first-name=Joe&last-name=Darling" ... ``` \n Note that now "first_name" and "last_name" parameters are a part of the query string now. Or you could write: \ ```bash ... export PATH_INFO="/add-customer/first-name/Joe" export QUERY_STRING="last-name=Darling" ... ``` \n Now, the input parameters are split between the path and the query string. \n \n Which form to use depends on the logic of your request. Use QUERY_STRING for additional information, and PATH_INFO to convey the logical hierarchy of resources needed by your request. That may sound a bit fuzzy, and it is. It's really up to you interpret your own application requirements the best you can. \n \n Either way, the result from calling the "shopping" executable above will be a customer ID, quoted so it's a valid JSON document. For instance it may be like this the very first time you run it: \n ```javascript "1" ``` \n ### Run as a web service \n REST applications are typically run on the web, so that's probably the most useful way. To do this, start your application as a FastCGI application server. You don't have to do anything to produce this kind of server, Vely has automatically created one when you built it. So to do this, use Vely's FastCGI process manager: \n ```bash vf --min-worker=3 --max-worker=10 shopping ``` \n This will start a server process (a daemon) that will remain running in the background. It will create worker processes for my application to handle requests. In this case, there will be a minimum of 3 and a maxium of 10 processes, depending on the load. The less requests come in, the less processes will run, and vice versa. This is the adaptive mode; see-[vf](https://vely.dev/vf.html), for more options. \n \n Anyway, now my application is running and is ready for use. For users (or applications) to send requests to it, I need a reverse-proxy, which would be a web server like Apache or Nginx, but it can be any web server that supports FastCGI, as most of them do. \n \n **Make a request from the web client** \ To test with a web server, here's how to do it. If you're using Apache server, make sure you have "proxy" and "proxy_fcgi" modules enabled. If you're using Nginx, that's already done for you by default so no worries. \ For Apache, I will add this to the configuration file (which would be "/etc/apache2/apache2.conf" or "/etc/httpd/conf/httpd.conf"): \n ```javascript ProxyPass "/api/v1/shopping" unix:///var/lib/vv/shopping/sock/sock|fcgi://localhost/shopping ``` \n Here I'm telling Apache to forward any URL that begins with "/api/v1/shopping" (remember that's what's specified in "--path" option when building the application) to the socket that Vely created for the application. Then I'll just restart Apache. \n \n For Nginx, I would edit the configuration file (either "/etc/nginx/sites-enabled/default" or "/etc/nginx/nginx.conf") and add to "server {}" section: \n ```javascript location /api/v1/shopping { include /etc/nginx/fastcgi_params; fastcgi_pass unix:///var/lib/vv/shopping/sock/sock; } ``` \n That does the exact same thing as for Apache. Restart Nginx for this to take effect. \n \n Once this is done, I can use this HTML form to call my REST API: \n \n ```go <form action="/api/v1/shopping/add-customer" method="POST"> <label for="first_name">First name:</label><br> <input type="text" name="first_name" value=""><br> <label for="last_name">Last name:</label><br> <input type="text" name="last_name" value=""><br><br> <input type="submit" value="Submit"> </form> ``` \n I can also use "curl" program to call from the command line. Notice that in this case, curl will do the exact same thing a browser would, which is to contact the web server, which in turn will talk to my FastCGI server in order to serve the request: \n ```bash curl -X POST "http://127.0.0.1/api/v1/shopping/add-customer/first-name/Joe/last-name/Darling" ``` \n \n **Make a request locally without a web server** \ This is useful when you don't want to setup a web server, but want to test it the same way a web server would. It works by sending a request to your application from the command line by using a [FastCGI_client](https://vely.dev/FastCGI_client.html). It looks similar to calling a command-line program, but unlike executing a program, it will actually contact the application server (that runs in the background) using socket communication, and get a reply from it: \n ```bash export REQUEST_METHOD=POST export SCRIPT_NAME="/api/v1/shopping" export PATH_INFO="/add-customer/first-name/Joe/last-name/Darling" export QUERY_STRING="" cgi-fcgi -connect /var/lib/vv/shopping/sock/sock / ``` \n The reply is of course the same as with a command line invocation - remember that no matter how you run a Vely application, it works the same! You can split parameters between PATH_INFO and QUERY_STRING just the same. \n ### Conclusion \n I've created a basic REST application and called my REST API in a number of ways. \n \n Now that you've learned the basics, you can proceed to a[complete REST example](https://vely.dev/example_shopping.html) that will continue adding to it, has a more complete functionality (including management of items and orders), and demonstrates the use of PUT, GET and DELETE methods as well. Not to worry, what you learned here should be enough to make the full example a breeze.