C++20 컴파일러, CMake 3.20+, OpenSSL이 필요합니다.
$ 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
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 -->
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
# 인증서 생성
$ 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;
}
app.get("/api/status").handle([](ynet::Request& req, ynet::Response& res) {
res.json("{\"status\":\"ok\",\"version\":\"0.1.0\"}");
});