DEV Community

Cover image for Solving Web Application Issues in C - The Greenest Programming Language
Sergio Mijatovic
Sergio Mijatovic

Posted on • Originally published at


Solving Web Application Issues in C - The Greenest Programming Language

C language and the Web

Even though a great deal of the world's 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, 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.

This article will show how to harness the power of C and smooth out the aforementioned issues.

What is Vely?

Vely is a general purpose framework for C developers. Applications created using Vely are native, without interpreters or byte-code schemes. See for more.

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. First is adding employees. The second one is showing the list of employees. The third one is being able to delete an employee from the list.

Before you start:

  1. Install Vely. You can use standard packagers like apt, dnf, zypper or pacman. Go to to install Vely. You can always remove it with the same packager,
  2. create a directory for your project - you can name it anything you want. All that's done here should be done in that directory,
  3. make sure you have MariaDB and Nginx installed, as they are used here.

Screenshots of application

Here are the snapshots of the application. This is the end result.

Web form to add an employee:

Add employee

The result of adding an employee:

Added employee

List the employees:

List employees

You can also delete an employee, and after that it won’t be in the list anymore.

Vely - how it works

In this article you'll create source code files for the application. The files have a .vely extension.

The source code in those files is C with Vely statements in it. Each statement will generate certain C code, so the end result is always C. That's how Vely works.

The part that makes Vely a framework is request handling - a simple dispatcher provides a foundation for standard HTTP request processing across the board. There’s also an automatic memory garbage collector, which is useful for long running processes such as web application daemons.

The bottom line is, Vely code will turn itself into pure C which is then compiled into a native application.

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 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>>
Enter fullscreen mode Exit fullscreen mode

Here's a few things to keep in mind when coding Vely:

Line continuation

Notice the usage of backslash (\) which, like in C, means the line continuation. So the first 3 lines of code are a single statement.

Outputting data

To display data to the web client (such as browser) or the standard output, use the output statement, which is the @ at the beginning of the line.

Database configuration

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:

Enter fullscreen mode Exit fullscreen mode

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.

Database queries

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.

Query results

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.

Query loops

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);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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:

Enter fullscreen mode Exit fullscreen mode

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 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>
    @<head><title>Vely example</title></head>

    pid_t pid = getpid(); // get current process ID

    @Employee report from process <<pf-out "%d", pid>>

    @<table border="1">

    run-query @db = \
        "select firstName, lastName, employeeID from employee" \
        output firstName, lastName, employeeID

            @<td> <<query-result lastName>> </td>
            @<td> <<query-result firstName>> </td>
            @<td> \
                <a href="?req=del_emp\
                    &employee_id=<<query-result employeeID>>">\
                </a> </td>
Enter fullscreen mode Exit fullscreen mode

As you see, 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 employee table, the employee's first and last name will be provided as input parameters. Those are simple to obtain in Vely framework by using input-param statement. 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!

    @Employee added
Enter fullscreen mode Exit fullscreen mode

Web form to add employees

In order to add employees, you will need a web form to enter them before sending off as input parameters to add_emp.vely for processing. Here is a simple form to do that - note the use of ? as action attribute in <form> element. It means: use the same URL path that led here, and then add the URL query string from 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>
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

Step 3: Create application

To create the Vely application, do this:

sudo vf -i -u $(whoami) emp
Enter fullscreen mode Exit fullscreen mode

-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 directory /var/lib/vv/emp, which is the application directory for your project (see how Vely works). You have initialized it and setup 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's 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
Enter fullscreen mode Exit fullscreen mode

-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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

and for Fedora, like RedHat:

sudo vi /etc/nginx/nginx.conf
Enter fullscreen mode Exit fullscreen mode

Add the following in the server {} section:

location /emp { include /etc/nginx/fastcgi_params; fastcgi_pass unix:///var/lib/vv/emp/sock/sock; }
Enter fullscreen mode Exit fullscreen mode

Restart Nginx for change to take effect:

sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

What you did here is connect the URL path /emp with the super-fast Unix socket connection between Nginx and your application servers. This way a URL like:

http://<your web server>/emp?req=add_emp&first_name=Joe&last_name=Darling
Enter fullscreen mode Exit fullscreen mode

would call function add_emp() in file add_emp.vely with first and last name 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:

http://<your web server>/emp?req=form_add_emp
Enter fullscreen mode Exit fullscreen mode

This one is to list employees

http://<your web server>/emp?req=emp
Enter fullscreen mode Exit fullscreen mode

Of course, replace “” with either "" loopback address (if you’re testing locally), or with your web server's fully qualified name or IP address.

Note these facts:

  1. the URL path is the name of your application - /emp in this case since that’s how you set it up with Nginx,
  2. the req parameter is always the base name of the request source file that handles it. For example, req=form_add_emp in URL means the code in form_add_emp.vely will handle the request,
  3. any other parameters you can freely choose.

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 Vely installation (thus bypassing the web server). In this case you would ask your application server to list the employee records:

export QUERY_STRING='req=emp'
cgi-fcgi -connect /var/lib/vv/emp/sock/sock /
Enter fullscreen mode Exit fullscreen mode

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 QUERY_STRING='req=add_emp&first_name=Joe&last_name=Darling'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

Enter fullscreen mode Exit fullscreen mode


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 deployment and for automated application testing.

Cover image copyright (c) 2022 Sergio Mijatovic

Top comments (0)

The most important JavaScript discussions happen on DEV

React vs Signals: 10 Years Later

React vs Signals: A Look Back

☝️ Ryan Carniato and Dan Abramov take a look back at React!