Quick Start

요구사항

C++20 컴파일러, CMake 3.20+, OpenSSL이 필요합니다.

CLI 설치

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

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

프로젝트 생성

$ ynet new myapp

$ cd myapp

$ ynet build

$ ynet run

브라우저에서 http://localhost:8080에 접속하면 Welcome 페이지가 나타납니다.

프로젝트 구조

myapp/

├── CMakeLists.txt

├── src/

│   └── main.cpp

├── static/

└── templates/

    └── index.html


라우팅

기본 라우팅

App 클래스의 메서드 체이닝으로 라우트를 등록합니다.

#include <ynet/app.h>

 

ynet::App app;

 

// GET 요청

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

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

});

 

// POST 요청

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

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

});

 

// PUT, DELETE

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

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

응답 메서드

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

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

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

res.redirect("/other");

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

쿼리 파라미터

// 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") + "!");

});

정적 파일 서빙

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

// static/ 폴더의 파일을 /static/ 경로로 서빙

커스텀 에러 핸들러

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

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


미들웨어

App 클래스 메서드로 미들웨어를 활성화합니다. 순서대로 실행됩니다.

app.logger();             // 요청 로깅

app.cors("*");           // CORS 허용

app.rateLimit(100, 60);   // 60초당 100요청 제한

app.csrf();             // CSRF 토큰 검증

app.sanitizer();        // 입력 검증

app.secureHeaders();    // 보안 헤더

app.session();          // 세션 관리

커스텀 CSP

// 기본 CSP

app.secureHeaders();

 

// 커스텀 CSP

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


템플릿 엔진

Mustache/Handlebars 스타일 문법을 지원합니다.

기본 사용법

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);

문법

<!-- 변수 (HTML 이스케이프) -->

문서 - yNet

 

<!-- Raw 출력 (이스케이프 없음) -->

 

<!-- 조건문 -->

 

<!-- 루프 -->

 

<!-- 파셜 include -->


WebSocket

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

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

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

    });

});


설정

프로젝트 루트의 config/프로젝트명.conf 파일로 설정합니다. 없으면 기본값으로 자동 생성됩니다.

# 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

HTTPS 활성화

# 인증서 생성

$ 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


예제

기본 서버

#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;

}

템플릿 + 미들웨어

#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\"}");

});