Quick Start

Requirements

C++20 compiler, CMake 3.20+, and OpenSSL are required.

Install CLI

$ git clone https://github.com/dvdsvds/yNet.git

$ sudo cp yNet/cli/ynet /usr/local/bin/

Create a Project

$ ynet new myapp

$ cd myapp

$ ynet build

$ ynet run

Open http://localhost:8080 in your browser to see the Welcome page.

Project Structure

myapp/

├── CMakeLists.txt

├── src/

│   └── main.cpp

├── static/

└── templates/

    └── index.html


Routing

Basic Routing

Register routes using method chaining on the App class.

#include <ynet/app.h>

 

ynet::App app;

 

// GET request

app.get("/").handle([](ynet::Request& req, ynet::Response& res) {

    res.html("<h1>Hello</h1>");

});

 

// POST request

app.post("/submit").handle([](ynet::Request& req, ynet::Response& res) {

    res.json("{\"ok\":true}");

});

 

// PUT, DELETE

app.put("/update").handle(...);

app.del("/remove").handle(...);

Response Methods

res.html("<h1>HTML</h1>");

res.json("{\"key\":\"value\"}");

res.status(201).body("Created");

res.redirect("/other");

res.header("X-Custom", "value");

Query Parameters

// GET /hello?name=dvd

app.get("/hello").handle([](ynet::Request& req, ynet::Response& res) {

    auto name = req.getQueryParam("name");

    res.html("Hello, " + name.value_or("World") + "!");

});

Static File Serving

app.serveStatic("/static", "static");

// Serves files from static/ directory at /static/ path

Custom Error Handlers

app.onError(404).html("<h1>Not Found</h1>");

app.onError(500).html("<h1>Server Error</h1>");


Middleware

Enable middleware via App class methods. They execute in order.

app.logger();             // Request logging

app.cors("*");           // CORS allow

app.rateLimit(100, 60);   // 100 req per 60 sec

app.csrf();             // CSRF token validation

app.sanitizer();        // Input sanitization

app.secureHeaders();    // Security headers

app.session();          // Session management

Custom CSP

// Default CSP

app.secureHeaders();

 

// Custom CSP

app.secureHeaders("default-src 'self'; style-src 'self' 'unsafe-inline'");


Template Engine

Supports Mustache/Handlebars-style syntax.

Basic Usage

ynet::Cache cache(256);

ynet::TemplateEngine engine(cache);

 

ynet::Object vars;

vars["title"] = ynet::JsonValue{std::string("Hello")};

 

std::string html = engine.render("templates/index.html", ynet::JsonValue{vars});

res.html(html);

Syntax

<!-- Variable (HTML escaped) -->

Docs - yNet

 

<!-- Raw output (no escaping) -->

 

<!-- Conditional -->

 

<!-- Loop -->

 

<!-- Partial include -->


WebSocket

app.ws("/chat", [](ynet::WebSocket& ws) {

    ws.onMessage([&](const std::string& msg) {

        ws.send("Echo: " + msg);

    });

});


Configuration

Configure via config/projectname.conf in the project root. A default file is auto-generated if missing.

# config/myapp.conf

port=8080

bind=0.0.0.0

tls=off

cert=cert.pem

key=key.pem

max_body=1MB

max_upload=10MB

max_header=8KB

max_headers=64

header_timeout=5000

body_timeout=10000

max_connections=1024

max_cache=1024

Enable HTTPS

# Generate certificate

$ openssl req -x509 -newkey rsa:2048 -keyout config/key.pem -out config/cert.pem -days 365 -nodes

 

# config/myapp.conf

port=443

tls=on

cert=cert.pem

key=key.pem


Examples

Basic Server

#include <ynet/app.h>

 

int main() {

    ynet::App app;

 

    app.get("/").handle([](ynet::Request& req, ynet::Response& res) {

        res.html("<h1>Hello, yNet!</h1>");

    });

 

    app.listen();

    return 0;

}

Template + Middleware

#include <ynet/app.h>

#include <ynet/util/template_engine.h>

#include <ynet/util/json.h>

 

int main() {

    ynet::App app;

 

    app.serveStatic("/static", "static");

    app.logger();

    app.secureHeaders();

 

    app.get("/").handle([](ynet::Request& req, ynet::Response& res) {

        ynet::Cache cache(256);

        ynet::TemplateEngine engine(cache);

 

        ynet::Object vars;

        vars["title"] = ynet::JsonValue{std::string("Home")};

 

        std::string html = engine.render("templates/index.html", ynet::JsonValue{vars});

        res.html(html);

    });

 

    app.listen();

    return 0;

}

JSON API

app.get("/api/status").handle([](ynet::Request& req, ynet::Response& res) {

    res.json("{\"status\":\"ok\",\"version\":\"0.1.0\"}");

});