18个版本 (2个稳定版)
1.0.1 | 2023年9月25日 |
---|---|
0.5.6 | 2023年3月24日 |
0.5.5 | 2023年2月18日 |
0.4.5 | 2022年12月5日 |
0.4.3 | 2022年11月17日 |
#159 in HTTP服务器
每月181次 下载
在 kickable 中使用
2.5MB
1K SLoC
Graphul 是一个受 Express 启发的 Web框架,使用强大的提取系统。Graphul旨在通过友好的语法改进、加速和扩展您的微服务,由 Rust 构建。这意味着Graphul可以免费获得内存安全、可靠性、并发性和性能,有助于在基础设施上节省资金。
用比特币买咖啡 ☕️
加入我们的Discord服务器,与其他Graphul社区成员交流!
⚡️ 快速入门
use graphul::{Graphul, http::Methods};
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/", || async {
"Hello, World 👋!"
});
app.run("127.0.0.1:8000").await;
}
👀 示例
以下是一些常见示例。如果您想看到更多代码示例,请访问我们的 示例文件夹
常见示例
🛫 Graphul 与最著名的框架对比

📖 上下文
use graphul::{http::Methods, Context, Graphul};
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
// /samuel?country=Colombia
app.get("/:name", |c: Context| async move {
/*
statically typed query param extraction
let value: Json<MyType> = match c.parse_params().await
let value: Json<MyType> = match c.parse_query().await
*/
let name = c.params("name");
let country = c.query("country");
let ip = c.ip();
format!("My name is {name}, I'm from {country}, my IP is {ip}",)
});
app.run("127.0.0.1:8000").await;
}
📖 JSON
use graphul::{Graphul, http::Methods, extract::Json};
use serde_json::json;
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/", || async {
Json(json!({
"name": "full_name",
"age": 98,
"phones": [
format!("+44 {}", 8)
]
}))
});
app.run("127.0.0.1:8000").await;
}
📖 资源
use std::collections::HashMap;
use graphul::{
async_trait,
extract::Json,
http::{resource::Resource, response::Response, StatusCode},
Context, Graphul, IntoResponse,
};
use serde_json::json;
type ResValue = HashMap<String, String>;
struct Article;
#[async_trait]
impl Resource for Article {
async fn get(c: Context) -> Response {
let posts = json!({
"posts": ["Article 1", "Article 2", "Article ..."]
});
(StatusCode::OK, c.json(posts)).into_response()
}
async fn post(c: Context) -> Response {
// you can use ctx.parse_params() or ctx.parse_query()
let value: Json<ResValue> = match c.payload().await {
Ok(data) => data,
Err(err) => return err.into_response(),
};
(StatusCode::CREATED, value).into_response()
}
// you can use put, delete, head, patch and trace
}
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.resource("/article", Article);
app.run("127.0.0.1:8000").await;
}
📖 静态文件
use graphul::{Graphul, FolderConfig, FileConfig};
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
// path = "/static", dir = public
app.static_files("/static", "public", FolderConfig::default());
// single page application
app.static_files("/", "app/build", FolderConfig::spa());
app.static_file("/about", "templates/about.html", FileConfig::default());
app.run("127.0.0.1:8000").await;
}
🌟 带自定义配置的静态文件
use graphul::{Graphul, FolderConfig, FileConfig};
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.static_files("/", "templates", FolderConfig {
// single page application
spa: false,
// it support gzip, brotli and deflate
compress: true,
// Set a specific read buffer chunk size.
// The default capacity is 64kb.
chunk_size: None,
// If the requested path is a directory append `index.html`.
// This is useful for static sites.
index: true,
// fallback - This file will be called if there is no file at the path of the request.
not_found: Some("templates/404.html"), // or None
});
app.static_file("/path", "templates/about.html", FileConfig {
// it support gzip, brotli and deflate
compress: true,
chunk_size: Some(65536) // buffer capacity 64KiB
});
app.run("127.0.0.1:8000").await;
}
📖 组
use graphul::{
extract::{Path, Json},
Graphul,
http::{ Methods, StatusCode }, IntoResponse
};
use serde_json::json;
async fn index() -> &'static str {
"index handler"
}
async fn name(Path(name): Path<String>) -> impl IntoResponse {
let user = json!({
"response": format!("my name is {}", name)
});
(StatusCode::CREATED, Json(user)).into_response()
}
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
// GROUP /api
let mut api = app.group("api");
// GROUP /api/user
let mut user = api.group("user");
// GET POST PUT DELETE ... /api/user
user.resource("/", Article);
// GET /api/user/samuel
user.get("/:name", name);
// GROUP /api/post
let mut post = api.group("post");
// GET /api/post
post.get("/", index);
// GET /api/post/all
post.get("/all", || async move {
Json(json!({"message": "hello world!"}))
});
app.run("127.0.0.1:8000").await;
}
📖 共享状态
use graphul::{http::Methods, extract::State, Graphul};
#[derive(Clone)]
struct AppState {
data: String
}
#[tokio::main]
async fn main() {
let state = AppState { data: "Hello, World 👋!".to_string() };
let mut app = Graphul::share_state(state);
app.get("/", |State(state): State<AppState>| async {
state.data
});
app.run("127.0.0.1:8000").await;
}
📖 与资源共享状态
use graphul::{
async_trait,
http::{resource::Resource, response::Response, StatusCode},
Context, Graphul, IntoResponse,
};
use serde_json::json;
struct Article;
#[derive(Clone)]
struct AppState {
data: Vec<&'static str>,
}
#[async_trait]
impl Resource<AppState> for Article {
async fn get(ctx: Context<AppState>) -> Response {
let article = ctx.state();
let posts = json!({
"posts": article.data,
});
(StatusCode::OK, ctx.json(posts)).into_response()
}
// you can use post, put, delete, head, patch and trace
}
#[tokio::main]
async fn main() {
let state = AppState {
data: vec!["Article 1", "Article 2", "Article 3"],
};
let mut app = Graphul::share_state(state);
app.resource("/article", Article);
app.run("127.0.0.1:8000").await;
}
📖 中间件
use graphul::{
Req,
middleware::{self, Next},
http::{response::Response,Methods},
Graphul
};
async fn my_middleware( request: Req, next: Next ) -> Response {
// your logic
next.run(request).await
}
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/", || async {
"hello world!"
});
app.middleware(middleware::from_fn(my_middleware));
app.run("127.0.0.1:8000").await;
}
📖 路由器
use graphul::{http::Methods, Graphul};
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/", || async { "Home" });
// you can use: Graphul::post, Graphul::put, Graphul::delete, Graphul::patch
let route_get = Graphul::get("/hello", || async { "Hello, World 👋!" });
// you can also use the `route` variable to add the route to the app
app.add_router(route_get);
app.run("127.0.0.1:8000").await;
💡 Graphul::router
use graphul::{
Req,
middleware::{self, Next},
http::{response::Response,Methods},
Graphul
};
async fn my_router() -> Graphul {
let mut router = Graphul::router();
router.get("/hi", || async {
"Hey! :)"
});
// this middleware will be available only on this router
router.middleware(middleware::from_fn(my_middleware));
router
}
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/", || async {
"hello world!"
});
app.add_router(my_router().await);
app.run("127.0.0.1:8000").await;
}
📖 模板
use graphul::{
http::Methods,
Context, Graphul, template::HtmlTemplate,
};
use askama::Template;
#[derive(Template)]
#[template(path = "hello.html")]
struct HelloTemplate {
name: String,
}
#[tokio::main]
async fn main() {
let mut app = Graphul::new();
app.get("/:name", |c: Context| async move {
let template = HelloTemplate { name: c.params("name") };
HtmlTemplate(template)
});
app.run("127.0.0.1:8000").await;
}
许可证
本项目采用 MIT许可证。
贡献
除非您明确声明,否则您有意向包含在 Graphul
中的任何贡献,都应按MIT许可,不附加任何额外条款或条件。
依赖项
~17MB
~375K SLoC