Version: v0.9.0

Architecture

In this section we are going to see some of the main components of Kalgan, its configuration, features, design patterns... That is to say, the internals of the framework.

Built-in Web Server

The first thing we must be aware is that Kalgan is not only a web framework but also incorporates a multithreaded web server which can handle concurrent connections simultaneously. The number of threads (workers) that the server contains defines the number of requests that our server can handle in parallel.

Server Internals

The server is based on the Multithreaded Web Server fully documented in Rust Book.

The server is made up by the following components, which for security reasons are private and won't be accessible from the app:

kalgan::server::tcp_listener The listener for TCP connections. Everytime we execute cargo run Kalgan triggers the std::net::TcpListener and this in turn creates the ThreadPool. The listener is bound to the settings parameters server.address and server.port.
kalgan::server::thread_pool A collection of spawned threads (workers) that are waiting to handle the request. The size of the pool depends on the settings parameter server.number_of_workers.
kalgan::server::worker Workers are the entities that handle the thread.

The flowchart below represents the startup sequence of the server:

After the startup the std::net::TcpListener keeps open waiting for the requests that come from the internet, which are finally passed to kalgan/src/handler/resolver.rs.

Server Configuration

As we have just seeen, there are a few settings parameters we must set to make the server works.

server.address IP/domain of the web server.
server.port Port of the web server.
server.number_of_workers Number of connections to handle at the same time. This parameter is not compulsory. When not present 10 is taken by default.

Our file settings.yaml should look at follows:

server:
    address: 127.0.0.1
    port: 7878
    number_of_workers: 10
...

Notice that these parameters are read by the server for the startup. Therefore, these are the only settings parameters which are not reload with every request while developing.

Request / Response

It is responsibility of the framework to manage the request which comes from the server and the response back to it. For this purpose it parses the request and creates the struct kalgan::http::request::Request which is passed to the application. In a reverse way, it transforms the struct kalgan::http::response::Response which comes from the application and pass a response to the server.

The below flowchart pictures this behaviour and shows how the server, the framework and the app communicate with each other:

Struct Request

As we said before, it is the kalgan/src/handler/resolver.rs who receives the request ( std::net::TcpStream ) from the server. It creates the kalgan::http::request::Request and sends it to the application handler.

Find the definition of the struct in the code below:

...
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Request<'a> {
    method: String,
    uri: String,
    protocol: String,
    cookies: HashMap<String, String>,
    host: String,
    user_agent: String,
    input: HashMap<String, String>,
    referer: String,
    #[serde(borrow)]
    files: HashMap<String, File<'a>>,
    raw: String,
    pub middleware: HashMap<String, String>,
    pub route: Option<Route>,
}
...

Notice that all the fields are private but Request.middleware and Request.route. This is because both fields are not part of the request, as they depend on the app route configuration, and are defined after the struct is created.

For more information regarding routing system go to Routing / URLs.

From a logical point of view, Request.middleware and Request.route shouldn't be included in the Request but we'll find they are extremely useful and save a lot of boilerplate. Regarding the private fields, these cannot not be altered and we'll have to use the methods commonly known as getters to get their value (for example Request.get_uri() ) .

Let take a look at these fields:

Request.method The HTTP Method (for example POST, GET, PUT, DELETE, etc).
Request.uri The HTTP URI.
Request.protocol The HTTP protocol version (for exmaple HTTP/1.0, HTTP/1.1, etc).
Request.cookies The cookies sent by the broser to the server.
Request.host The IP address or domain.
Request.user_agent Information regarding the Operating System and the browser.
Request.input Parameters sent as a body of the request, after the headers. These are the data typically sent by a HTML form.
Request.referer Address of the web page which is linked to the resource requested.
Request.files Collection of files sent with the request.
Request.raw The original request without being parsed.
Request.middleware The parameters sent by the middleware to the controller.
Request.route The route that matches the request.

Struct Response

The kalgan/src/handler/resolver.rs is responsible as well of giving back a response to the server. It receives the kalgan::http::response::Response from the application handler, converts it into a Vec<u8> and finally sends it to the server.

Find the definition of the struct in the code below:

...
#[derive(Debug, Clone)]
pub struct Response {
    status: String,
    content_type: String,
    location: String,
    cookies: Vec,
    content: String,
    content_length: String,
}
...

Notice that all fields are private, we don't need to access to their value as this is information is just for the server. However we are responsible of setting these values, for which we'll have to use the methods commonly known as setters (for example Response.set_status() ).

Let take a look at these fields:

Response.status The HTTP response status code (for example 200, 404, 301, etc).
Response.content_type The media type of the resource.
Response.location The URL to redirect a page to. It only provides a meaning when served with a 3xx or 201 status code.
Response.cookies Collection of cookies sent to the browser.
Response.content The content of the resourcer.
Response.content_length The size of the resource.

Regarding the status code, these are the only codes which are currently supported:

200 HTTP/1.1 200 OK
301 HTTP/1.1 301 Moved Permanently
302 HTTP/1.1 302 Found
403 HTTP/1.1 403 Forbidden
404 HTTP/1.1 404 Not Found
500 HTTP/1.1 500 Internal Server Error
503 HTTP/1.1 503 Service Unavailable

MVC Pattern

Kalgan is an MVC framework, which means it's divided in 3 main logical layers: model, view and controller. This is probably one of the most common design patterns (architectural pattern) when building user interfaces. MVC separates the business logic (model) and presentation layer (view) from each other.

The below flowchart represents this design:

Let's take just a brief look at these layers. So much has been written about MVC pattern and a deeper approach is out of the scope of this documentation.

Model Layer

The model component stores the application data and related business logic. It only communicates with the controller or other model components. It's commonly related to the database entities but not necessarily as not all entitites can (or need) be mapped to a database.

For more information regarding models and database management go to Database / SQLx in the docs.

View Layer

This is the component that renders the UI using the data passed from the controller. In web applications this is mainly reated to HTML views but this is not the only option (think in a JSON response for a web service or XML for feeds, for example).

For more information regarding view templates go to Templates / Tera in the docs.

Controller Layer

The controller is the only layer which communicates with the other two. First it receives the request from the server (user). Then it calls the model to retrieve the data and the view to retrieve the data representation. Finally it gives back the response to the user.

For more information regarding controllers go to Handlers in the docs.

Services

Kalgan comes with a few built-in services which might help with some of most common tasks in web development. These services are located under kalgan/src/service/.

kalgan::service::csrf::* Provides support to migitate CRSF attack (see CSRF Attack in the docs).
kalgan::service::db::* A collection of functions to create the database connection pool (see Database / SQLx in the docs).
kalgan::service::password::* Functions for password management based on Argon2 hash (see Password Storage in the docs).
kalgan::service::118n::trans Returns the translated message (see i18n / Translation in the docs).
kalgan::service::mailer::send_email Sends an email through a SMTP server (see Mailer / SMTP in the docs).
kalgan::service::token::generate Returns a random alphanumeric string with the given length.
kalgan::service::url::generate Returns the URI (see Routing / URLs in the docs).

Features

Kalgan offers some feature flags to reduce the amount of compiled code. Somehow Kalgan could be considered as a microframework out of the box as most of its components are optional. We must be aware that Kalgan doesn't enable any of them by default.

Find below the list of the available feature flags:

kalgan_i18n Enables translation system powered by create i18n (see i18n / Translation in the docs).
mailer Enables the emailing system powered by crate lettre (see Mailer / SMTP in the docs).
services Enables the services kalgan::service::password and kalgan::service::token.
kalgan_cache Enables the cache system that runs on Redis (see Cache / Redis in the docs).
session Enables the session management that runs on cache system (see Cookies / Sessions in the docs).
sqlx Enables the database connection powered by crate sqlx (see Database / SQLx in the docs).
tera Enables the templating system powered by crate Tera (see Templates / Tera in the docs).
test Enables the traits and functions to mock objects while testing (see Tests in the docs).
full Enables all the features but test.

Notice that the only component that is not optional is the Routing System.

Kalgan Crates

Kalgan depends on several external crates. It also depends on a few internal crates, which were created specifically for the framework. However this crates are decoupled from the framework and can be used outside Kalgan.

These crates are:

kalgan_router Contains all the logic for the routing system used in Kalgan.
kalgan_i18n Contains all the logic for the translation system used in Kalgan.
kalgan_config Contains all the logic for the configuration system used in Kalgan.
kalgan_cache A wrapper for crate redis, used for Kalgan session system.
kalgan_string A small collection of auxiliary functions to work with strings.