访问users数据库
This commit is contained in:
2
.env
Normal file
2
.env
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# .env
|
||||||
|
DATABASE_URL=postgres://milkydata:44n6FdB8CdDAk5rk@154.37.213.24:5432/milkydata
|
||||||
1158
Cargo.lock
generated
1158
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -5,4 +5,7 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.11.0"
|
actix-web = "4.11.0"
|
||||||
serde = "1.0.219"
|
chrono = "0.4.41"
|
||||||
|
dotenvy = "0.15.7"
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] }
|
||||||
|
|||||||
10
src/db.rs
Normal file
10
src/db.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
use sqlx::postgres::PgPool; // 修改导入路径
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
pub async fn create_pool() -> Result<PgPool, sqlx::Error> {
|
||||||
|
dotenvy::dotenv().ok();
|
||||||
|
let database_url = env::var("DATABASE_URL")
|
||||||
|
.expect("DATABASE_URL must be set in .env file");
|
||||||
|
|
||||||
|
PgPool::connect(&database_url).await
|
||||||
|
}
|
||||||
141
src/main.rs
141
src/main.rs
@@ -1,61 +1,98 @@
|
|||||||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
|
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
|
||||||
use serde::{Deserialize, Serialize};
|
use models::User;
|
||||||
|
use db::create_pool;
|
||||||
|
use sqlx::postgres::PgPool;
|
||||||
|
|
||||||
// 定义响应数据结构
|
mod models;
|
||||||
#[derive(Serialize)]
|
mod db;
|
||||||
struct GreetingResponse {
|
|
||||||
message: String,
|
#[get("/users")]
|
||||||
|
async fn get_users(pool: web::Data<PgPool>) -> impl Responder {
|
||||||
|
let query = r#"
|
||||||
|
SELECT id, "name", openid, phone, "type", "desc"
|
||||||
|
FROM users
|
||||||
|
LIMIT 10
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = sqlx::query_as::<_, User>(query)
|
||||||
|
.fetch_all(pool.get_ref())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(users) => {
|
||||||
|
println!("Successfully fetched {} users", users.len());
|
||||||
|
HttpResponse::Ok().json(users)
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Database error: {}", e);
|
||||||
|
HttpResponse::InternalServerError().body(format!("Database error: {}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义请求数据结构
|
// 创建服务器配置的函数
|
||||||
#[derive(Deserialize)]
|
fn create_server_config(pool: PgPool) -> App<impl actix_web::dev::ServiceFactory<
|
||||||
struct UserRequest {
|
actix_web::dev::ServiceRequest,
|
||||||
name: String,
|
Config = (),
|
||||||
age: u8,
|
Response = actix_web::dev::ServiceResponse,
|
||||||
}
|
Error = actix_web::Error,
|
||||||
|
InitError = (),
|
||||||
// 健康检查端点
|
>> {
|
||||||
#[get("/health")]
|
App::new()
|
||||||
async fn health_check() -> impl Responder {
|
.app_data(web::Data::new(pool))
|
||||||
HttpResponse::Ok().body("Service is healthy")
|
.service(get_users)
|
||||||
}
|
|
||||||
|
|
||||||
// 根路径处理
|
|
||||||
#[get("/")]
|
|
||||||
async fn index() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body("Welcome to Rust Web Backend!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 带参数的问候端点
|
|
||||||
#[get("/greet/{name}")]
|
|
||||||
async fn greet(name: web::Path<String>) -> impl Responder {
|
|
||||||
let response = GreetingResponse {
|
|
||||||
message: format!("Hello, {}!", name),
|
|
||||||
};
|
|
||||||
HttpResponse::Ok().json(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST 请求处理
|
|
||||||
#[post("/user")]
|
|
||||||
async fn create_user(user: web::Json<UserRequest>) -> impl Responder {
|
|
||||||
let response = GreetingResponse {
|
|
||||||
message: format!("Created user: {} (age {})", user.name, user.age),
|
|
||||||
};
|
|
||||||
HttpResponse::Created().json(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
println!("Starting server at http://localhost:80");
|
// 初始化数据库连接池
|
||||||
|
let pool = match create_pool().await {
|
||||||
|
Ok(pool) => pool,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to create database pool: {}", e);
|
||||||
|
eprintln!("Please check your database connection configuration in .env file");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
HttpServer::new(|| {
|
println!("Attempting to start server...");
|
||||||
App::new()
|
|
||||||
.service(health_check)
|
// 尝试多个端口
|
||||||
.service(index)
|
let ports = vec![8080, 3000, 8000, 8888];
|
||||||
.service(greet)
|
let mut server = None;
|
||||||
.service(create_user)
|
|
||||||
})
|
for port in ports {
|
||||||
.bind("0.0.0.0:80")?
|
let addr = format!("127.0.0.1:{}", port);
|
||||||
.run()
|
println!("Trying to bind to {}", addr);
|
||||||
.await
|
|
||||||
|
// 为每个服务器创建克隆的连接池
|
||||||
|
let pool_clone = pool.clone();
|
||||||
|
|
||||||
|
match HttpServer::new(move || create_server_config(pool_clone.clone()))
|
||||||
|
.bind(&addr) {
|
||||||
|
Ok(s) => {
|
||||||
|
println!("Successfully bound to {}", addr);
|
||||||
|
server = Some(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to bind to {}: {}", addr, e);
|
||||||
|
if e.kind() == std::io::ErrorKind::PermissionDenied {
|
||||||
|
eprintln!(" -> Permission denied. Try running with sudo or use a port > 1024");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match server {
|
||||||
|
Some(s) => {
|
||||||
|
println!("Server started successfully");
|
||||||
|
s.run().await
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
eprintln!("Failed to bind to any port. Please check your system configuration.");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
20
src/models.rs
Normal file
20
src/models.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use sqlx::FromRow;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, FromRow)]
|
||||||
|
pub struct User {
|
||||||
|
pub id: i32,
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
#[sqlx(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
#[sqlx(rename = "openid")]
|
||||||
|
pub openid: Option<String>,
|
||||||
|
#[sqlx(rename = "phone")]
|
||||||
|
pub phone: Option<String>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
#[sqlx(rename = "type")]
|
||||||
|
pub user_type: i32,
|
||||||
|
#[serde(rename = "desc")]
|
||||||
|
#[sqlx(rename = "desc")]
|
||||||
|
pub description: Option<String>,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user