Tuesday, November 12, 2024

Multi-tenant SaaS (Notes web application) in 200 lines of code

This is a complete SaaS example (Software-as-a-Service) using PostgreSQL as a database, and Gliimly as a web service engine; it includes user signup/login/logout with an email and password, separate user accounts and data, and a notes application. All in about 200 lines of code! Here's a video that shows it - two users sign up and create their own notes:

First create a directory for your application, where the source code will be:
mkdir -p notes
cd notes

Setup Postgres database
Create PostgreSQL user (with the same name as your logged on Linux user, so no password needed), and the database "db_app":
echo "create user $(whoami);
create database db_app with owner=$(whoami);
grant all on database db_app to $(whoami);
\q"  | sudo -u postgres psql

Create a database configuration file to describe your PostgreSQL database above:
echo "user=$(whoami) dbname=db_app" > db_app

Create database objects we'll need - users table for application users, and notes table to hold their notes:
echo "create table if not exists notes (dateOf timestamp, noteId bigserial primary key, userId bigint, note varchar(1000));
create table if not exists users (userId bigserial primary key, email varchar(100), hashed_pwd varchar(100), verified smallint, verify_token varchar(30), session varchar(100));
create unique index if not exists users1 on users (email);" | psql -d db_app

Create Gliimly application
Create application "notes" owned by your Linux user:
sudo mgrg -i -u $(whoami) notes

Source code
This executes before any other handler in an application, making sure all requests are authorized, file "before-handler.gliim":
vi before-handler.gliim

Copy and paste:
 before-handler
     set-param displayed_logout = false, is_logged_in = false
     call-handler "/session/check"
 end-before-handler


- Signup users, login, logout

This is a generic session management web service that handles user creation, verification, login and logout. Create file "session.gliim":

Sunday, November 10, 2024

Gliimly 91 released

  • Fixed SELinux installation bug for Fedora-like distros.
  • Minimum number of CPUs available is 1 in case there's an issue in determining the number of them.
  • Fixed issue with highlighting call-handler statement in vim.

Tuesday, November 5, 2024

Gliimly 87 released

  • Added --exclude option to gg in order to exclude sub-directories from compilation.
  • Added p-source-line and p-source-file statements to aid in debugging.
  • A request handler can now be defined in any source file whose path matches, partially or fully, the request path of the handler. For instance /session/login request handler can be defined either in file "session.gliim" or "session/login.gliim". A source file can also have multiple request handlers that match path.
  • Added --single-file option to gg to force each source code file to have just a single request handler.
  • set-param and get-param statements now work with multiple parameters separated by a comma.
  • set-cookie and get-cookie statements now work with multiple cookies separated by a comma.
  • Fixed bug in end-write-string statement where junk text at the end would be ignored without an error message.
  • Fixed error in parallel compilation.
  • Fixed bug in get-param where parameter name wouldn't be correct.
  • Fixed bug where a function in call-extended statement wouldn't work without any parameters.

Monday, October 28, 2024

Gliimly 76 released

  • Major enhancement: request handler source files can now be written in (sub)directories, such that the path leading to the request handler matches the request path. For instance, request handler "/session/user/new" will be implemented under directories "session", then "user", and then in file new.gliim. This allows for clean and easy to organize structure of an application.
  • Fixed bug in parallel compilation, where reported file names in error messages were inaccurate.
  • Faster compilation by using soft links instead of copies where needed.
  • sub-handler statement has been renamed call-handler for better descriptiveness.
  • Added "public" and "private" clauses in begin-handler, to improve security features. "private" means that request handler cannot be called by an outside caller (formerly "sub-handler").
  • Added --public option in gg to toggle between request handlers being public or private by default (by default they are private).
  • Fixed spurious output from gg -m.
  • Better error message when trying to compile an application and it was not yet created.
  • p-path statement now must have a request path object, in order to make a more reliable construction of link URL paths, and to allow for static checking of requests, for faster design and development.
  • begin-handler statement now must start with a forward slash, which was up until now optional.

Web Services Security

The security of web services is a broad subject, but there are a few common topics that one should be well aware. They affect if your web application, or an API service, will be a success or not.

Many web services provide an interface to a database. SQL injection is a very old, but nonetheless important issue. A naive implementation of SQL execution inside your code could open the door for a malicious actor to drop your tables, insert/update/delete records etc. Be sure that your back-end software is SQL injection proof.

Wednesday, October 23, 2024

Gliimly 70 released

  • Enhanced compiler error message in if-true statement when conditional statement is missing or incomplete.
  • Fixed bug in p-path statement where it wouldn't work without new-line clause.
  • Fixed bug in set/get-param statements where it (rarely) may get stuck in wrong compiled code.
  • C style comment /*...*/ will cause an error at the beginning of statement only for readability and to avoid library detection issues.
  • Better error message when database config file is not found for a database.  

Monday, October 21, 2024

Web services with MariaDB

Create a directory for your project, it'll be where this example takes place. Also create Gliimly application "stock":
mkdir -p stock-app
cd stock-app
sudo mgrg -i -u $(whoami) stock

Start MariaDB command line interface:
sudo mysql

Create an application user, database and a stock table (with stock name and price):
create user stock_user;
create database stock_db;
grant all privileges on stock_db.* to stock_user@localhost identified by 'stock_pwd';
use stock_db
create table if not exists stock (stock_name varchar(100) primary key, stock_price bigint);

Gliimly wants you to describe the database: the user name and password, database name, and the rest is the default setup for MariaDB database connection. So create a file "db_stock" (which is your database configuration file, one per each you use):

Saturday, October 19, 2024

Gliimly 65 released

  • Added --parallel option to gg utility to enable multi-threaded compilation. Now the speed of making large application can be multiple times faster, for instance 3-5 times faster with a typical laptop.
  • Added high-performance hash for parameters (see set-param, get-param), making them comparable to C's stack variables in performance.
  • Removed input-count, input-name, input-value clauses from get-req statement as they are superfluous now.
  • set-param enhanced by making =<value> optional. This is often used when parameter name and the variable assigned to it have the same name. It makes the code reading and writing cleaner.

Thursday, October 17, 2024

Web service calling web service


A web service doesn't necessarily need to be called from "the web", meaning from the web browser or via API across the web. It can be called from another web service that's on a local network.

Typically, when called from the web, HTTPS protocol is used to ensure safety of that call. However, local networks are usually secure, meaning no one else has access to it but your own web services.

Thus, communication between local web services will be much faster if it doesn't use a secure protocol as it incurs the performance cost. Simple, fast and unburdened protocols, such as FastCGI, may be better.

Monday, October 14, 2024

Gliimly 56 released

Fixed bug with before-handler and after-handler statements, where the names of files used to implement them (.gliim files) were not correctly stated in the documentation.

Sunday, October 13, 2024

What is Web Service


Web service is code that responds to a request and provides a reply over HTTP protocol. It doesn't need to work over the web, despite its name. You can run a web service locally on a server or on a local network. You can even run a web service from command line. In fact, that's an easy way to test them.

The input comes from an HTTP request - this means via URL parameters plus (optional) request body.

Friday, October 11, 2024

Cache as a web service


This example shows Apache as the front-end (or "reverse proxy") for cache server - it's assumed you've completed it first. Three steps to setting up Apache quickly:

Wednesday, October 9, 2024

Cache server in 30 lines


This is a cache server that can add, delete and query key/value pairs, with their number limited only by available memory.

We'll use "index" type, which is a high-performance data structure. For example, with 1,000,000 keys it will take only about 20 comparisons to find any key; and the range search is just one hop. Index is based on a modified AVL/B tree.

Create new "index" application first, in a new directory (you can name it anything you like):
mkdir -p index
cd index

The mgrg command is a Gliimly service manager and here it will create a new application named "index" (it can be different from the directory it's in):
sudo mgrg -i -u $(whoami) index

Create a source code file "srv.gliim":

Tuesday, October 8, 2024

Gliimly 54 released

  • Improvement: Faster gg utility for services execution from command line (-r option)
  • Bug fix:  "-z" option in mgrg would have no effect in some cases, meaning the silent header would not be honored and the HTTP header would always be output, specifically if "--silent-header" is omitted in "gg -r". This now works as documented. 

Sunday, October 6, 2024

Memory safety: the cost in performance


Memory safety guards against software security risks and malfunctions by assuring data isn't written to or read from unintended areas of memory. It prevents leaks, and that's important for web services which are long-running processes - memory leaks usually lead to running out of memory and crashes.

But what of the performance cost of memory safety?  Gliimly is a very high level programming language. It's not like other languages, and you can intuitively experience that just by looking at the code. It feels more like speaking in English than moving bits and bytes or calling APIs.

So when you build your web services, you won't write a lot of code, rather you'd express what you want done in a declarative language, and natively-compiled high-performance C code will do the rest. This code is designed to be memory safe, but because it's C, it avoids the penalty of being implemented in a general-purpose memory-safe language, where everything that's done, from bottom up and top down, would be subject to memory-safety checks.

Tuesday, October 1, 2024

Gliimly 50 released

 New features and improvements:

  • Added HMAC (Hash Message Authentication Code) support with hmac-string statement.
  • Updated OpenSSL-based statements handling to be able to use custom digests/ciphers available in version 3+.

Sunday, September 29, 2024

SQLite with Gliimly


This example will create a service that inserts key and value into SQLite table. It's tested from command line.

Create a directory and then switch to it:
mkdir sqlite
cd sqlite

Setup SQLite database in file "mydata.db":
echo 'drop table if exists key_value; 
create table if not exists key_value (key varchar(50) primary key, value varchar(100));' | sqlite3 mydata.db

Create configuration file "mydb" that describes the SQLite database "mydata.db":
echo "$(pwd)/mydata.db"> mydb

Create the application:
sudo mgrg -i -u $(whoami) sqlite

Create file insert.gliim:
vim insert.gliim

Copy and paste to it (note use of database configuration "mydb" in @mydb):
 %% /insert public
     get-param key
     get-param value
     run-query @mydb = "insert into key_value(key,value) values ('%s', '%s')" input key, value error err affected-rows aff_rows no-loop
     @Error <<p-out err>>, affected rows <<p-num aff_rows>>
 %%

Compile the application - we specify that file "mydb" is describing SQLite database:
gg -q --db=sqlite:mydb

Run the application by executing this service from command line. Note passing the input parameters "key" and "value" to it:
gg -r --req="/insert/key=1/value=one" --exec --silent-header

The output is:
Error 0, affected rows 1

Verify data inserted:
echo -e ".headers off\n.mode line\nselect key "Key", value "Value" from key_value"|sqlite3 mydata.db

The result:
Key = 1
Value = one

Copy-code icon added

Copy icon () is now in the upper right corner of all code blocks in Gliimly documentation, as well as this blog.

Click this icon to copy the code. This is useful for getting the sample code in your own, learning Gliimly etc.

Friday, September 27, 2024

Gliimly 44 released

Bug fixes:
  • Fixed bug where a memory for parameters or split-string type could be allocated with no data causing invalid write in debug mode only. 
  • Fixed bug where passing a number from sub-request back to the caller would not be correct or could cause invalid memory read.
  • Fixed bug in encryption statement (encrypt-data) with checking memory bounds of Initialization Vector (IV).
  • Fixed bug in executing SQL with any database. The bug was with checking the formatting of the statement.
New features and improvements:
  • Added -z command-line option to Service Manager (mgrg). This option suppresses HTTP header  for all service requests in application (equivalent to implicit silent-header statement at the beginning of each request handler).
  • Improved performance of piping output from execution of programs in exec-program statement.
  • Improved performance of message composition in write-message statement.
  • Structured types can now be returned to caller from sub-handler - for instance creating a new index or array.

Thursday, September 26, 2024

Overview of Gliimly


Gliimly is a new programming language and framework for developing web services and web applications. The reason for Gliimly is to make software development easier, more reliable and to improve run-time performance. To do this, Gliimly is a very high level language yet it's a high performance one; those two qualities aren't usually together.

Gliimly is a declarative language designed for simplicity. That means top-down approach, rather than bottom-up: it's more about describing what to do than coding it. It's a modeling language where pieces are assembled together quickly and with confidence. It's about the framework to create and deploy web services with less effort and faster.

Gliimly is a memory-safe language. Your program is safe from overwriting memory it shouldn't overwrite, and it won't leave dangling pointers hanging around. Gliimly is a static-typed language with only three basic types (strings, numbers and boolean) and (currently) the following structured types: service, message, array, index, index-cursor, fifo, lifo, list, split-string and file.

Tuesday, September 24, 2024

Gliimly 37 released

  • Added "new-line" clause to output statements, such as p-out, p-web, p-url, p-path and p-num. This clause adds new line to the output of any of these statements.
  • Fixed bug in write-string where program errors out in some cases with multiple use of encoded output statements, such as p-web for instance.

Saturday, September 21, 2024

Web service Hello World


To access a Gliim service on the web, you need to have a web server or load balancer (think Apache, Nginx, HAProxy etc.).

This assumes you have completed the Hello World as a Service, with a service built and tested via command line.

In this example, Nginx web server is used; edit its configuration file. For Ubuntu and similar:
sudo vi /etc/nginx/sites-enabled/default

while on Fedora and other systems it might be:
sudo vi /etc/nginx/nginx.conf

Add the following in the "server {}" section:
location /hello/ { include /etc/nginx/fastcgi_params; fastcgi_pass  unix:///var/lib/gg/hello/sock/sock; }

"hello" refers to your Hello World application. Finally, restart Nginx:
sudo systemctl restart nginx

Now you can call your web service, from the web. In this case it's probably a local server (127.0.0.1) if you're doing this on your own computer. The URL would be:
http://127.0.0.1/hello/hello-world/name=Mike

Note the URL request structure: first comes the application path ("/hello") followed by request path ("/hello-world") followed by URL parameters ("/name=Mike"). The result:

Hello World as a Service


Writing a service is the same as writing a command-line program in Gliim. Both take the same input and produce the same output, so you can test with either one to begin with.

For that reason, create first Hello World as a command-line program.

The only thing to do afterwards is to start up Hello World as application server:
mgrg hello

Now there's a number of resident processes running, expecting clients requests. You can see those processes:
ps -ef|grep hello

The result:
bear       25772    2311  0 13:04 ?        00:00:00 mgrg hello
bear       25773   25772  0 13:04 ?        00:00:00 /var/lib/gg/bld/hello/hello.srvc
bear       25774   25772  0 13:04 ?        00:00:00 /var/lib/gg/bld/hello/hello.srvc
bear       25775   25772  0 13:04 ?        00:00:00 /var/lib/gg/bld/hello/hello.srvc
bear       25776   25772  0 13:04 ?        00:00:00 /var/lib/gg/bld/hello/hello.srvc
bear       25777   25772  0 13:04 ?        00:00:00 /var/lib/gg/bld/hello/hello.srvc

"mgrg hello" runs the Gliim process manager for application "hello". A number of ".../hello.srvc" processes are server processes that will handle service request sent to application "hello".

Now, to test your service, you can send a request to the server from command line (by using "--service" option):
gg -r --req="/hello-world/name=Mike" --exec --silent-header --service

The above will make a request to one of the processes above, which will then reply:
This is Hello World from Mike

Friday, September 20, 2024

Gliimly 32 released

  • HTTP header is now sent to client by default at the very first output, i.e. the equivalent of 'out-header default' statement.No code change is necessary. Typical use of out-header is to send default headers at the very beginning of a service, and those can in general be removed now, since it's done automatically.

  • Color scheme is now supported for Gliimly source code. Prior to this release, there was one hardcoded colorscheme. Now your can use any available color  scheme to customize look and feel of source code in Vim editor (use ":colorscheme" command).

Thursday, September 19, 2024

Using Vim color schemes with Gliimly


Gliimly installation comes with a Vim module for highlighting Gliimly code. After installing Gliimly, run this to install the Vim module:
gg -m

The default color scheme looks like this:
To change color scheme, type ":colorscheme " in command mode, then press Tab to see available color schemes. Press Enter to choose one. For instance, in 'darkblue' color scheme, it may look like:
To make the change permanent, edit file ".vimrc" in home directory:
vi ~/.vimrc

and append line:
colorscheme darkblue