16 个版本
0.0.26 | 2020年8月24日 |
---|---|
0.0.25 | 2020年8月22日 |
0.0.19 | 2020年2月18日 |
#672 in HTTP 服务器
每月 51 次下载
135KB
3.5K SLoC
邮政局
这是一个轻量级的 TCP 连接管理器,包括客户端和服务器端功能,用于通过消息队列以高速、长连接稳定地通信,使用 Rust 编写。
安装
将 crate 名称和版本放入您的 cargo.toml 文件中的依赖项部分。
postoffice = "*"
API 层
- TCP 连接 - 模块:client,server
- Json 请求结果处理器 - 模块:resp
- 服务器端请求的 Json 方案验证 - 模块:check
Tcp 连接
基础 TCP 连接使用自定义的 UTF 字符串作为请求分隔符,以字节的形式传输。
客户端请求
简单请求
SMPL sdf67sf678sd6f sdf78sd6f78sdfsdfsdf+=\r\n
这里第一个术语是请求标识符,然后是请求 ID 和 base64 编码的字符串。
加密请求
SMPL sdf67sf678sd6f sdf87sd89fsd987f789sd7f8sd97f+:sdf78sd6f78sdfsdfsdf+=\r\n
这里第一个术语是请求标识符,然后是请求 ID、base64 编码的 nonce 和密文,由 ':' 分隔。
服务器响应
这些响应由处理函数作为 Response 结构返回,并按以下方式解析。
成功响应
//encrypted
match Response::new(req,"secure message".to_string(),true) {
Ok(res)=>{
return Ok(res);
},
Err()=>{
return Resp::error(req,"parser failed".to_string());
}
}
//simple
match Response::new(req,"unsecure message".to_string(),false) {
Ok(res)=>{
return Ok(res);
},
Err()=>{
return Resp::error(req,"parser failed".to_string());
}
}
OK sdf67sf678sd6f sdf87sd89fsd987f789sd7f8sd97f+:sdf78sd6f78sdfsdfsdf+=\r\n
这里第一个术语是结果标识符,然后是请求 ID 和由 ':' 分隔的 base64 编码的 nonce 和密文(用于加密消息)以及普通的 base64 编码字符串(用于正常响应)。
错误响应
错误响应正如其名,它们可能携带错误和请求标识符,但如果解析失败,则错误响应不会通过给定的 ID 识别请求。
BAD parser-failed\r\n
此响应发生在解析请求数据失败时。
处理函数的自定义错误
return Ok(resp::error(req,"hanlder ran out of mem".to_string()));
BAD sdf67sf678sd6f "hanlder ran out of mem"\r\n
处理函数的未定义错误
return Ok(resp::bad(req));
BAD sdf67sf678sd6f undefined\r\n
服务器使用
use postoffice::{server,resp,common};
use postoffice::check::{Field,Format};
use json::JsonValue;
fn handler(req: Request) -> Result<Response,String> {
let mut new_format = Format::new();
new_format.field_builder(vec![
Field::new("string",false,"type",vec!["write","read","collection_check","collection_insert"],Field::no_format(),0,0,false),
Field::new("object",false,"data",Field::no_options(),Field::no_format(),0,0,false)
]);
let body:JsonValue;
match check::check_request(req.clone(),new_format) {
Ok(parsed)=>{
body = parsed;
},
Err(e)=>{
let error = format!("check request failed error : {:?}",e);
return Ok(resp::error(req,error));
}
}
let child_format = Format::builder(vec![
Field::new("string",false,"id",Field::no_options(),Field::no_format(),0,0,false),
Field::new("string",false,"path",Field::no_options(),Field::no_format(),0,0,false),
Field::new("array",false,"users",Field::no_options(),Field::no_format(),0,100,true)
]);
match check::check_children(&body["data"], "object".to_string(), Field::no_options(), child_format, false, true) {
Ok(_)=>{},
Err(e)=>{
let error = format!("check children failed error : {:?}",e);
return Ok(resp::error(req,error));
}
}
let mut user_format = Format::new();
user_format.field_builder(vec![
Field::new("string",false,"name",Field::no_options(),Field::no_format(),0,0,false),
Field::new("string",false,"email",Field::no_options(),Field::no_format(),0,0,false),
Field::new("string",false,"company",Field::no_options(),Field::no_format(),2,50,true)
]);
for entry in body["data"].entries() {
let data = entry.1;
let users = &data["users"];
match check::check_array(&users, "object".to_string(), Field::no_options(), &user_format) {
Ok(_)=>{},
Err(e)=>{
let error = format!("check array failed error : {:?}",e);
return Ok(resp::error(req,error));
}
}
}
return Ok(resp::ok(req));
}
fn auth(token:server::auth::Token) -> bool {
println!("token : {:?}",token);
return true;
}
fn main(){
let key = "8cfb30b34977529853bbe46afdbbd5ae".to_string();
let address = String::from("127.0.0.1:5200");
server::init(address,key,handler,auth);
}
客户端使用
use postoffice::client::{get_random_connection_id,start_connection,send_message};
use postoffice::resp;
fn main(){
let key = "8cfb30b34977529853bbe46afdbbd5ae".to_string();
let connection_id = client::get_random_connection_id();
let addr = "127.0.0.1:5200".to_string();
match start_connection(&connection_id,addr,key) {
Ok(_)=>{
//println!("connection establishged");
},
Err(_)=>{
common::error("failed start connection");
}
}
let mut user = JsonValue::new_object();
user.insert("name","akku").unwrap();
user.insert("email","[email protected]").unwrap();
user.insert("company","daachi.in").unwrap();
let mut users = JsonValue::new_array();
users.push(user);
let mut request = JsonValue::new_object();
request.insert("collection","1a62c37cf70a74cfeb69aba742643613").unwrap();
request.insert("path","/users/");
request.insert("users",users);
send(connection_id,request);
}
fn send(connection_id:String,data:json::JsonValue){
let mut request_object = json::JsonValue::new_object();
match request_object.insert("type","write") {
Ok(_)=>{},
Err(_)=>{}
}
match request_object.insert("data",data) {
Ok(_)=>{},
Err(_)=>{}
}
let request_string = request_object.dump();
match client::send_message(&connection_id,request_string,false) {
Ok(response)=>{
match resp::parse_response(response) {
Ok(result)=>{
println!("result : {:?}",result);
},
Err(e)=>{
println!("error parse response strucft : {:?}",e);
}
}
},
Err(_)=>{
println!("request failed");
}
}
}
请确保适当更新测试。
许可
MIT
依赖
~5MB
~79K SLoC