This how u solve the Web Application Issues in C - the Greatest Programming Language ever, by Mahdad Kiyani!
Mahdad Kiyani
AWS Partner (APN-Software Solutions) | AWS SA Professional | Azure AZ-305 | ML & Data Engineering | IT Governance & SAFe Agilist | ITIL Leader | MBA (expected june 2025) | ISO 27001 Lead Auditor
As we all know C programming is defined (and well known) as one of the most powerful programming language, in that it allows direct access to memory and many low-level computer operations. C is one of the lowest level languages that is still fairly readable (compared to binary code with 0's and 1's)
C programming and the Web
Although most of the web infrastructure is written in C, most people don’t think of C to write web applications. And that’s understandable, given C’s lack of easy-to-use web and database constructs, no direct connectivity to web servers, and safety issues, just to name a few.
C, however, is the world’s?greenest programming language, and that’s important if we want to help the environment. It certainly doesn’t hurt that if you want the best performance, C is the language to use.
In this article I will show how to unleash the power of C and smooth out the web issues.
Introducing Vely?
Vely is a general-purpose framework for C developers. Applications created using Vely are native, without interpreters or byte-code schemes.
The application you'll write and run
You'll write a Human Resources (HR) web application that maintains the list of employees. It's simple and not quite bursting with bells and whistles, but it demonstrates enough to get started. And you wouldn't want a tutorial meant for learning to be cluttered with all kinds of things you can easily add on your own. The purpose here is to learn the basics.
So to that end, there are three parts to this.
Before you start:
Screenshots of application
Here are the snapshots of the application. This is the end result.
Web form to add an employee:
Introduction to using SQL
First I'll talk about using databases, as it's the foundation for database-driven web applications.
Vely currently supports MariaDB/mySQL, PostgreSQL, and SQLite databases. The interface is the same for any of them. For example, to query table?employee?and display a list of names found, here's the Vely code:
run-query @db = \
"select firstName, lastName from employee where employeeID='%s'" \
output firstName, lastName \
: empid
@Employee is <<query-result firstName>> <<query-result lastName>>
end-query
Here are a few things to keep in mind when coding Vely:
Notice the usage of backslash (\) which, like in C, means the line continuation. So the first 3 lines of code are a single statement.
To display data to the web client (such as a browser) or the standard output, use the output statement, which is the?@?at the beginning of the line.
The database is specified with?@?clause, in this case, it's?@db. This is the file that holds the native database connection information. Each database has its own; in this case, you're using MariaDB (or mySQL), and so file?db?might have the following content:
[client]
user=user_name
password=password
database=database_name
socket=/run/mysqld/mysqld.sock
You can read more on the?details?of writing a connection string information for MariaDB/mySQL. Vely uses native database connectivity for performance, and the connection details are native too. This covers much of what you need in order to query a database in C using Vely.
To run a query, use?run-query?statement. Typically it states the database used (with?@?clause), the query itself, and the list of output columns (with?output?clause). You supply input parameters for the SQL statement after?:?clause.
To display column data from the query's result-set, use?query-result?statement. When used in the output, as is the case here, you can place it within?<<?and?>>?- that's inline code.
If you want to loop through the result-set of your query, mark the end of this loop with?end-query?statement, like above.
Step 1: Getting started - the database
First, you will create the database and employee table used here. The SQL in this example is simple, so you can use any database vendor you want. Here though, MariaDB is used. The SQL to create the employee table is as follows. Save this to?setup.sql?file:
create table if not exists employee (
firstName varchar(50),
lastName varchar(50),
employeeID integer primary key auto_increment);
Login to mySQL utility as a root user (database admin) and execute this to create the database, user, and employee table:
create database if not exists emp;
create user if not exists appuser identified by 'my_password';
grant create,alter,drop,select,insert,delete,update
on emp.* to appuser;
use emp;
source setup.sql;
exit
Finally, Vely needs to know where is your database. Create the database configuration file?db?(that's the name used in run-query statements). Copy this to file?db:
[client]
user=appuser
password=my_password
database=emp
protocol=TCP
host=127.0.0.1
port=3306
Note the?appuser?and?emp?database (as well as the password) are the same as in the creation sql you executed in mysql utility.
Step 2: Source code
Here's the source code. Copy and paste the code to the files as instructed.
List employees (query a table)
This will display a list of employees from the employee table. Just to illustrate the usage of any C code, (since most of the code here is Vely statements), I've added the C code to find out the Process ID (PID) and display it. Save this to?emp.vely?file:
#include "vely.h"
void emp()
{
out-header default
@<!DOCTYPE html>
@<html>
@<head><title>Vely example</title></head>
@<body>
pid_t pid = getpid(); // get current process ID
@Employee report from process <<pf-out "%d", pid>>
@<hr/>
@<table border="1">
run-query @db = \
"select firstName, lastName, employeeID from employee" \
output firstName, lastName, employeeID
@<tr>
@<td> <<query-result lastName>> </td>
@<td> <<query-result firstName>> </td>
@<td> \
<a href="?req=del_emp\
&employee_id=<<query-result employeeID>>">\
Delete\
</a> </td>
@</tr>
end-query
@</table>
@</body>
@</html>
}
As you see, the output statement?@?is used a lot. It outputs any text that follows on the same line. Since the same Vely program can serve as a web application and as a command-line program, the output's destination depends on how you use it. If it's a web application, the output goes to the web client, i.e. a browser. If it's a command-line program, the output goes to the standard output, i.e.?stdout.
While outputting data, the inline code is often used as part of the output. Inline code is written between?<<?and?>>?and typically calls a Vely statement that outputs something. In this example,?query-result?outputs the column values of a query result-set.
Note you'll have the ability to delete an employee record by clicking the Delete link. The link calls back your application and specifies which employee record to delete based on?employeeID?that's embedded in the delete link.
All Vely requests must have a?req?input parameter, specifying what?.vely?file will handle the request. So when the user clicks the link, code in?del_emp.vely?will run. That's coming up.
Add an employee (insert into table)
To insert data into the employee table, the employee's first and last name will be provided as input parameters. Those are simple to obtain in the Vely framework by using?input-param?statements. Then, INSERT SQL will insert the data with?run-query, which uses?no-loop?clause to say that there's no result-set loop (i.e. this isn't a SELECT query), and?affected-rows?to get the number of rows actually inserted. Finally, you'll check if a row was inserted as expected, and inform the user. Save this code to?add_emp.vely?file:
#include "vely.h"
void add_emp() {
out-header default
input-param first_name
input-param last_name
run-query @db = \
"insert into employee (firstName, lastName) \
values ('%s', '%s')" \
: first_name, last_name \
no-loop \
affected-rows define aff_rows
if (aff_rows != 1) {
@Could not add employee!
exit-request
}
@Employee added
}
Web form to add employees
In order to add employees, you will need a web form to enter them before sending them off as input parameters to?add_emp.vely?for processing. Here is a simple form to do that - note the use of?"?"?as an action attribute in <form> element. It means: use the same URL path that led here and then add the URL query string from the form's input fields.
Note the hidden field?req?which is a mandatory field that Vely needs in order to route the HTTP requests - unsurprisingly it contains?add_emp. Save this to form_add_emp.vely?file:
#include "vely.h"
void form_add_emp() {
out-header default
@<h2>Enter employee</h2>
@<form action="?" method="POST">
@ <input type="hidden" name="req" value="add_emp">
@ <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>
}
Delete an employee (delete from table)
Deleting an employee record will obtain the employee ID, and issue a DELETE SQL statement. Note the use of?:?clause, which lets you specify the SQL input parameters, in this case?employee_id?to be deleted. Save this to?del_emp.vely?file:
领英推荐
#include "vely.h"
void del_emp() {
out-header default
input-param employee_id
run-query @db = \
"delete from employee where employeeID='%s'" : employee_id \
no-loop \
affected-rows define aff_rows
if (aff_rows == 1) {
@Employee record deleted.
} else {
@Could not delete an employee record.
}
}
Step 3: Create application
To create the Vely application, do this:
sudo vf -i -u $(whoami) emp
-i?says create a Vely application,?-u?says the owner of it will be the current user, and?emp?is the application name.
This will create a directory?/var/lib/vv/emp, which is the application directory for your project (see?how Vely works). You have initialized it and set up permissions to allow the current user to use this directory, while other users cannot access it.
Step 4: Make application
You now have the following files in your project:?emp.vely,?form_add_emp.vely,?add_emp.vely,?del_emp.vely?and?db. Vely'?vv utility?will make an application out of them - it will automatically find these files and generate a proper Makefile for you and link in the necessary libraries.
You can make the application with?vv:
vv -q --db=mariadb:db
-q?says you're making the application.?--db?says you're using MariaDB database and the database configuration file is in the file db.
Note you can use multiple databases in your application, and from different vendors too.
Step 5: Run application
You will run the application as a FastCGI application server. Your application server runs behind the web server (in this case Nginx), which acts as a reverse proxy. A number of persistent and concurrent server processes will serve the incoming requests. The processes do not exit and they work in parallel. Also, they are not directly accessible to the end user.
To start your application:
vf -w 5 emp
This will start 5 concurrent processes. Read about?vf - Vely's FastCGI process manager?for more on how you can fine-tune performance, including setting up a dynamic process loader that varies the number of processes running based on the actual runtime load.
Step 6: Setup Nginx for FastCGI
The final step is to setup a web server, Nginx in this case. Edit the Nginx configuration file - for Ubuntu and similar Linux distros:
sudo vi /etc/nginx/sites-enabled/default
and for Fedora, like RedHat:
sudo vi /etc/nginx/nginx.conf
Add the following in the "server {}" section:
location /emp { include /etc/nginx/fastcgi_params; fastcgi_pass unix:///var/lib/vv/emp/sock/sock; }
Restart Nginx for change to take effect:
sudo systemctl restart nginx
Here, you connected the URL path "/emp" with the super-fast Unix socket connection between Nginx and your application servers. This way a URL like:
https://<your web server>/emp?req=add_emp&first_name=Joe&last_name=Darling
would call function?add_emp()?in file?add_emp.vely?with first and last names as input parameters.
That’s it
You now have a functional application ready to use. The following describes various ways to use it.
Using application from web browser
The following URLs are the interface to your application. Use both to run it. The first is to add an employee:
https://<your web server>/emp?req=form_add_emp
This one is to list employees
https://<your web server>/emp?req=emp
Of course, replace “<your web server>” with either "127.0.0.1" loopback address (if you’re testing locally), or with your web server's fully qualified name or IP address.
Note these facts:
Note that if you don't have a web server, and you still want to use your application server, you can contact it directly on the command line with the FastCGI client included in the Vely installation (thus bypassing the web server). In this case, you would ask your application server to list the employee records:
export REQUEST_METHOD=GET
export QUERY_STRING='req=emp'
cgi-fcgi -connect /var/lib/vv/emp/sock/sock /
Command-line usage
Every Vely application can run as a web application or as a command-line program. They also both use HTTP as a protocol, making it easy to develop, test, maintain and use the application in a myriad of different ways.
Note that if you plan to solely run your application from the command-line, you do not need the application server, so in that case, you don't need the web server setup nor do you need to start the application server using vf process manager. It's much simpler.
To run your application from the command line, provide the input parameters on the command line and run the program. For instance to add an employee, provide REQUEST_METHOD environment variable (such as GET), and QUERY_STRING (set to URL to add an employee), and invoke the program:
export REQUEST_METHOD=GET
export QUERY_STRING='req=add_emp&first_name=Joe&last_name=Darling'
/var/lib/vv/bld/emp/emp
The result is:
Content-type: text/html;charset=utf-8
Cache-Control: max-age=0, no-cache
Pragma: no-cache
Status: 200 OK
Employee added
If you plan to save the result in a file (for example to cache the application output), you can omit the HTTP header from the output by doing this:
export VV_SILENT_HEADER=yes
Conclusion
In this tutorial, you have learned how to create a fully-functional database-driven web application with Vely that uses MariaDB/mySQL as a database and Nginx as a reverse-proxy web server.
You could have used PostgreSQL and Apache for instance, and it would be very similar.
You have also learned how to run your application in different ways: as an application server or from the command-line. The output and behavior are exactly the same, which is useful for both deployments and for automated application testing.
Cover image copyright (c) 2022 Sergio Mijatovic