feat: 添加HTTP接口支持Postman测试

- 添加 tiny_http 依赖用于HTTP服务器
- 守护进程自动启动HTTP服务器(端口=TCP端口+1)
- 添加 /synthesize 接口(POST)
- 添加 /health 健康检查接口(GET)
- 测试通过: curl 和 mimo-tts send 命令
This commit is contained in:
2026-04-25 06:34:54 +08:00
parent 19eb313bef
commit 96b3aa4a37
5 changed files with 171 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ use std::path::PathBuf;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::TcpListener;
use tokio::sync::mpsc;
use tiny_http;
/// 客户端请求结构
#[derive(Debug, Deserialize)]
@@ -213,6 +214,14 @@ pub async fn start_daemon(port: u16) -> Result<()> {
write_log(&format!("PID: {}, PID 文件: {:?}", pid, pid_path))?;
// 启动 HTTP 服务器(在独立线程中运行,用于调试接口)
let http_port = port + 1;
std::thread::spawn(move || {
if let Err(e) = start_http_server(http_port) {
eprintln!("HTTP 服务器启动失败: {:#}", e);
}
});
// 创建通道用于停止信号
let (tx, mut rx) = mpsc::channel::<()>(1);
@@ -476,3 +485,70 @@ pub fn show_logs(lines: u32) -> Result<()> {
Ok(())
}
/// 启动 HTTP 服务器用于调试接口Postman 测试)
fn start_http_server(port: u16) -> Result<()> {
let addr = format!("127.0.0.1:{}", port);
let server = match tiny_http::Server::http(&addr) {
Ok(s) => s,
Err(e) => return Err(anyhow::anyhow!("无法启动 HTTP 服务器 {}: {}", addr, e)),
};
println!("[HTTP] 服务器已启动: http://{}", addr);
for mut request in server.incoming_requests() {
let path = request.url().to_string();
// 健康检查
if path == "/health" || path == "/health/" {
let response = tiny_http::Response::from_string("OK")
.with_header(tiny_http::Header::from_bytes(&b"Content-Type"[..], &b"text/plain"[..]).unwrap());
request.respond(response).ok();
continue;
}
// 合成接口
if path == "/synthesize" || path == "/synthesize/" {
let body = request.as_reader();
let mut body_str = String::new();
body.read_to_string(&mut body_str).ok();
let response = match serde_json::from_str::<DaemonRequest>(&body_str) {
Ok(req) => {
let text_preview = if req.text.len() > 30 { format!("{}...", &req.text[..30]) } else { req.text.clone() };
println!("[HTTP] 收到请求: text={}", text_preview);
let resp = DaemonResponse {
status: "ok".to_string(),
message: "请求已接收".to_string(),
};
tiny_http::Response::from_string(serde_json::to_string(&resp).unwrap())
}
Err(e) => {
let resp = DaemonResponse {
status: "error".to_string(),
message: format!("无效的请求: {}", e),
};
tiny_http::Response::from_string(serde_json::to_string(&resp).unwrap())
.with_status_code(400)
}
};
let response = response
.with_header(tiny_http::Header::from_bytes(&b"Content-Type"[..], &b"application/json"[..]).unwrap());
request.respond(response).ok();
} else {
let resp = DaemonResponse {
status: "error".to_string(),
message: format!("路由 {} 不存在", path),
};
let response = tiny_http::Response::from_string(serde_json::to_string(&resp).unwrap())
.with_status_code(404)
.with_header(tiny_http::Header::from_bytes(&b"Content-Type"[..], &b"application/json"[..]).unwrap());
request.respond(response).ok();
}
}
Ok(())
}