Web Rust 网络编程示例
Web Rust 网络编程示例,包括HTTP请求、HTTP服务器和TCP套接字
💻 HTTP请求 rust
🟢 simple
⭐⭐⭐
使用reqwest或hyper crate发送GET和POST请求
⏱️ 20 min
🏷️ rust, web, networking, http
Prerequisites:
Basic Rust, reqwest crate, tokio
// Web Rust HTTP Request Examples
// Using reqwest crate for HTTP client functionality
use std::collections::HashMap;
use std::time::Duration;
// Note: This requires the reqwest crate
// Add to Cargo.toml:
// [dependencies]
// reqwest = { version = "0.11", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// 1. Basic GET Request
/// Simple GET request
async fn simple_get_request(url: &str) -> Result<String, Box<dyn std::error::Error>> {
let response = reqwest::get(url).await?;
let body = response.text().await?;
Ok(body)
}
/// GET request with headers
async fn get_with_headers(url: &str) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(10))
.build()?;
let response = client
.get(url)
.header("User-Agent", "My Rust Client")
.header("Accept", "application/json")
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
/// GET request with query parameters
async fn get_with_query_params(
base_url: &str,
params: &HashMap<String, String>,
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.get(base_url)
.query(params)
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
// 2. POST Request
/// POST JSON data
async fn post_json(
url: &str,
data: &serde_json::Value,
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.post(url)
.header("Content-Type", "application/json")
.json(data)
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
/// POST form data
async fn post_form(
url: &str,
form_data: &HashMap<String, String>,
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.post(url)
.form(form_data)
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
/// POST raw bytes
async fn post_bytes(
url: &str,
data: &[u8],
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.post(url)
.body(data.to_vec())
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
// 3. Response Handling
/// Get response headers
async fn get_response_headers(url: &str) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
let response = reqwest::get(url).await?;
let mut headers = HashMap::new();
for (key, value) in response.headers() {
headers.insert(
key.as_str().to_string(),
value.to_str().unwrap_or("").to_string(),
);
}
Ok(headers)
}
/// Check response status
async fn check_status(url: &str) -> Result<bool, Box<dyn std::error::Error>> {
let response = reqwest::get(url).await?;
Ok(response.status().is_success())
}
/// Download file
async fn download_file(url: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::get(url).await?;
let bytes = response.bytes().await?;
tokio::fs::write(output_path, &bytes).await?;
Ok(())
}
// 4. HTTP Client with Configuration
/// Create custom HTTP client
fn create_http_client() -> reqwest::Client {
reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.connect_timeout(Duration::from_secs(10))
.pool_max_idle_per_host(10)
.build()
.expect("Failed to create client")
}
/// Reusable client for multiple requests
async fn multiple_requests(base_url: &str) -> Result<(), Box<dyn std::error::Error>> {
let client = create_http_client();
// First request
let _response1 = client.get(&format!("{}/users", base_url)).send().await?;
// Second request
let _response2 = client
.get(&format!("{}/posts", base_url))
.send()
.await?;
Ok(())
}
// 5. Authentication
/// Basic authentication
async fn basic_auth_request(
url: &str,
username: &str,
password: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.get(url)
.basic_auth(username, Some(password))
.send()
.await?;
Ok(response.text().await?)
}
/// Bearer token authentication
async fn bearer_auth_request(
url: &str,
token: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.get(url)
.header("Authorization", format!("Bearer {}", token))
.send()
.await?;
Ok(response.text().await?)
}
// Usage Examples
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust HTTP Request Examples ===\n");
// 1. Simple GET
println!("--- 1. Simple GET Request ---");
match simple_get_request("https://httpbin.org/get").await {
Ok(body) => println!("Response: {}\n", &body[..std::cmp::min(200, body.len())]),
Err(e) => println!("Error: {}\n", e),
}
// 2. GET with headers
println!("--- 2. GET with Headers ---");
match get_with_headers("https://httpbin.org/headers").await {
Ok(body) => println!("Response: {}\n", &body[..std::cmp::min(200, body.len())]),
Err(e) => println!("Error: {}\n", e),
}
// 3. POST JSON
println!("--- 3. POST JSON ---");
let data = serde_json::json!({"key": "value", "number": 42});
match post_json("https://httpbin.org/post", &data).await {
Ok(body) => println!("Response: {}\n", &body[..std::cmp::min(200, body.len())]),
Err(e) => println!("Error: {}\n", e),
}
// 4. Check status
println!("--- 4. Check Status ---");
match check_status("https://httpbin.org/status/200").await {
Ok(success) => println!("Request successful: {}\n", success),
Err(e) => println!("Error: {}\n", e),
}
println!("=== All HTTP Request Examples Completed ===");
Ok(())
}
💻 HTTP服务器 rust
🟡 intermediate
⭐⭐⭐⭐
使用hyper或actix-web框架创建HTTP服务器
⏱️ 30 min
🏷️ rust, web, networking, server
Prerequisites:
Intermediate Rust, hyper crate, tokio
// Web Rust HTTP Server Examples
// Using hyper crate for HTTP server functionality
use std::collections::HashMap;
use std::convert::Infallible;
use std::net::SocketAddr;
// Note: This requires the hyper and tokio crates
// Add to Cargo.toml:
// [dependencies]
// hyper = { version = "0.14", features = ["full"] }
// tokio = { version = "1", features = ["full"] }
// 1. Basic HTTP Server
/// Basic hello world server
async fn basic_server() {
#[hyper::server::macros::service]
fn hello_world(_req: hyper::Body) -> hyper::Response<hyper::Body> {
hyper::Response::new(hyper::Body::from("Hello, World!"))
}
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let server = hyper::Server::bind(&addr).serve(hyper::service(hello_world));
println!("Listening on http://{}", addr);
if let Err(e) = server.await {
eprintln!("Server error: {}", e);
}
}
// 2. Route-Based Server
/// Simple router
struct Router {
routes: HashMap<String, hyper::Body>,
}
impl Router {
fn new() -> Self {
let mut routes = HashMap::new();
routes.insert("/".to_string(), hyper::Body::from("Home Page"));
routes.insert("/about".to_string(), hyper::Body::from("About Page"));
routes.insert("/contact".to_string(), hyper::Body::from("Contact Page"));
Router { routes }
}
fn handle(&self, req: hyper::Request<hyper::Body>) -> hyper::Response<hyper::Body> {
let path = req.uri().path();
match self.routes.get(path) {
Some(body) => hyper::Response::new(body.clone()),
None => hyper::Response::builder()
.status(hyper::StatusCode::NOT_FOUND)
.body(hyper::Body::from("404 - Not Found"))
.unwrap(),
}
}
}
/// Run router server
async fn router_server() {
let router = Router::new();
let make_service = hyper::service::make_service_fn(move |_| {
let router = router.clone();
async move {
Ok::<_, Infallible>(hyper::service::service_fn(move |req| {
async move { Ok::<_, Infallible>(router.handle(req)) }
}))
}
});
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let server = hyper::Server::bind(&addr).serve(make_service);
println!("Router listening on http://{}", addr);
if let Err(e) = server.await {
eprintln!("Server error: {}", e);
}
}
// 3. JSON API Server
/// User data structure
#[derive(serde::Serialize, serde::Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
/// Handle GET /users
async fn get_users() -> hyper::Response<hyper::Body> {
let users = vec![
User { id: 1, name: "Alice".to_string(), email: "[email protected]".to_string() },
User { id: 2, name: "Bob".to_string(), email: "[email protected]".to_string() },
];
match serde_json::to_string(&users) {
Ok(json) => hyper::Response::new(hyper::Body::from(json)),
Err(_) => hyper::Response::builder()
.status(hyper::StatusCode::INTERNAL_SERVER_ERROR)
.body(hyper::Body::from("Error serializing JSON"))
.unwrap(),
}
}
/// Handle POST /users
async fn create_user(body: hyper::Body) -> hyper::Response<hyper::Body> {
let whole_body = match hyper::body::to_bytes(body).await {
Ok(bytes) => bytes,
Err(e) => {
return hyper::Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(hyper::Body::from(format!("Error reading body: {}", e)))
.unwrap();
}
};
match serde_json::from_slice::<User>(&whole_body) {
Ok(user) => {
match serde_json::to_string(&user) {
Ok(json) => hyper::Response::builder()
.status(hyper::StatusCode::CREATED)
.body(hyper::Body::from(json))
.unwrap(),
Err(_) => hyper::Response::builder()
.status(hyper::StatusCode::INTERNAL_SERVER_ERROR)
.body(hyper::Body::from("Error serializing JSON"))
.unwrap(),
}
}
Err(e) => hyper::Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(hyper::Body::from(format!("Invalid JSON: {}", e)))
.unwrap(),
}
}
/// API request handler
async fn api_handler(req: hyper::Request<hyper::Body>) -> hyper::Response<hyper::Body> {
let method = req.method().clone();
let uri = req.uri().clone();
let path = uri.path();
match (method.as_str(), path) {
("GET", "/users") => get_users().await,
("POST", "/users") => create_user(req.into_body()).await,
_ => hyper::Response::builder()
.status(hyper::StatusCode::NOT_FOUND)
.body(hyper::Body::from("404 - Not Found"))
.unwrap(),
}
}
/// Run API server
async fn api_server() {
let make_service = hyper::service::make_service_fn(|_| async {
Ok::<_, Infallible>(hyper::service::service_fn(|req| {
async move { Ok::<_, Infallible>(api_handler(req).await) }
}))
});
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let server = hyper::Server::bind(&addr).serve(make_service);
println!("API server listening on http://{}", addr);
if let Err(e) = server.await {
eprintln!("Server error: {}", e);
}
}
// 4. Server with Middleware
/// Middleware to log requests
async fn logging_middleware(
req: hyper::Request<hyper::Body>,
next: hyper::body::Sender,
) -> Result<hyper::Response<hyper::Body>, Infallible> {
println!("{} {}", req.method(), req.uri().path());
// In a real implementation, you would call the next handler here
Ok(hyper::Response::new(hyper::Body::from("Logged")))
}
/// Middleware to add CORS headers
fn add_cors_headers(mut response: hyper::Response<hyper::Body>) -> hyper::Response<hyper::Body> {
response.headers_mut().insert("Access-Control-Allow-Origin", "*".parse().unwrap());
response.headers_mut().insert("Access-Control-Allow-Methods", "GET, POST, OPTIONS".parse().unwrap());
response
}
// 5. Static File Server
/// Serve static files
async fn serve_static(file_path: &str) -> hyper::Response<hyper::Body> {
match tokio::fs::read(file_path).await {
Ok(contents) => {
let mime_type = mime_guess::from_path(file_path)
.first_or_octet_stream()
.to_string();
hyper::Response::builder()
.header("Content-Type", mime_type)
.body(hyper::Body::from(contents))
.unwrap()
}
Err(_) => hyper::Response::builder()
.status(hyper::StatusCode::NOT_FOUND)
.body(hyper::Body::from("File not found"))
.unwrap(),
}
}
// Usage Examples
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust HTTP Server Examples ===\n");
println!("Choose server type:");
println!("1. Basic server");
println!("2. Router server");
println!("3. API server");
println!();
println!("Uncomment the server you want to run:");
println!("basic_server().await;");
println!("router_server().await;");
println!("api_server().await;");
// Example: Start basic server (commented out)
// basic_server().await;
Ok(())
}
💻 TCP套接字 rust
🟡 intermediate
⭐⭐⭐
创建TCP连接并构建TCP服务器和客户端
⏱️ 25 min
🏷️ rust, web, networking, tcp
Prerequisites:
Intermediate Rust, std::net
// Web Rust TCP Socket Examples
// Using std::net for TCP networking
use std::io::{BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::time::Duration;
// 1. TCP Server
/// Simple echo server
fn run_echo_server(address: &str) -> std::io::Result<()> {
let listener = TcpListener::bind(address)?;
println!("Echo server listening on {}", address);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
handle_client(stream)?;
}
Err(e) => {
eprintln!("Error accepting connection: {}", e);
}
}
}
Ok(())
}
/// Handle individual client connection
fn handle_client(mut stream: TcpStream) -> std::io::Result<()> {
let peer_addr = stream.peer_addr()?;
println!("New connection from {}", peer_addr);
let mut reader = BufReader::new(&stream);
loop {
let mut line = String::new();
let bytes_read = reader.read_line(&mut line)?;
if bytes_read == 0 {
break;
}
print!("Received: {}", line);
// Echo back
stream.write_all(line.as_bytes())?;
}
println!("Connection closed from {}", peer_addr);
Ok(())
}
// 2. TCP Client
/// Connect to TCP server
fn connect_to_server(address: &str) -> std::io::Result<TcpStream> {
TcpStream::connect(address)
}
/// Send message to server
fn send_message(stream: &mut TcpStream, message: &str) -> std::io::Result<()> {
stream.write_all(message.as_bytes())?;
stream.flush()
}
/// Read response from server
fn read_response(stream: &mut TcpStream) -> std::io::Result<String> {
let mut reader = BufReader::new(stream);
let mut response = String::new();
reader.read_line(&mut response)?;
Ok(response)
}
/// Simple TCP client
fn run_echo_client(address: &str) -> std::io::Result<()> {
let mut stream = connect_to_server(address)?;
println!("Connected to {}", address);
// Send message
let message = "Hello, TCP Server!\n";
send_message(&mut stream, message)?;
println!("Sent: {}", message.trim());
// Read response
let response = read_response(&mut stream)?;
println!("Received: {}", response.trim());
Ok(())
}
// 3. Multi-threaded Server
/// Multi-threaded echo server
fn run_multi_threaded_server(address: &str) -> std::io::Result<()> {
let listener = TcpListener::bind(address)?;
println!("Multi-threaded server listening on {}", address);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
thread::spawn(move || {
if let Err(e) = handle_client(stream) {
eprintln!("Error handling client: {}", e);
}
});
}
Err(e) => {
eprintln!("Error accepting connection: {}", e);
}
}
}
Ok(())
}
// 4. Server with Protocol
/// Chat message
#[derive(Debug)]
struct ChatMessage {
username: String,
content: String,
}
impl ChatMessage {
fn parse(line: &str) -> Option<ChatMessage> {
let parts: Vec<&str> = line.splitn(2, ':').collect();
if parts.len() == 2 {
Some(ChatMessage {
username: parts[0].trim().to_string(),
content: parts[1].trim().to_string(),
})
} else {
None
}
}
fn format(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
/// Chat server
fn run_chat_server(address: &str) -> std::io::Result<()> {
let listener = TcpListener::bind(address)?;
println!("Chat server listening on {}", address);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
thread::spawn(move || {
if let Err(e) = handle_chat_client(stream) {
eprintln!("Error handling chat client: {}", e);
}
});
}
Err(e) => {
eprintln!("Error accepting connection: {}", e);
}
}
}
Ok(())
}
/// Handle chat client
fn handle_chat_client(mut stream: TcpStream) -> std::io::Result<()> {
let peer_addr = stream.peer_addr()?;
println!("Chat client connected from {}", peer_addr);
// Welcome message
stream.write_all(b"Welcome to the chat server!\n")?;
let mut reader = BufReader::new(&stream);
loop {
let mut line = String::new();
let bytes_read = reader.read_line(&mut line)?;
if bytes_read == 0 {
break;
}
if let Some(msg) = ChatMessage::parse(&line) {
println!("Chat: {:?}", msg);
let response = format!("Message received: {}\n", msg.content);
stream.write_all(response.as_bytes())?;
} else {
stream.write_all(b"Invalid message format. Use: username: message\n")?;
}
}
println!("Chat client disconnected: {}", peer_addr);
Ok(())
}
// 5. TCP Client with Timeout
/// Connect with timeout
fn connect_with_timeout(address: &str, timeout: Duration) -> std::io::Result<TcpStream> {
TcpStream::connect_timeout(&address.parse().unwrap(), timeout)
}
/// Client with timeout
fn run_timeout_client(address: &str) -> std::io::Result<()> {
let timeout = Duration::from_secs(5);
match connect_with_timeout(address, timeout) {
Ok(mut stream) => {
println!("Connected to {}", address);
stream.set_read_timeout(Some(timeout))?;
stream.set_write_timeout(Some(timeout))?;
send_message(&mut stream, "Hello\n")?;
let response = read_response(&mut stream)?;
println!("Response: {}", response.trim());
Ok(())
}
Err(e) => {
Err(e)
}
}
}
// 6. Broadcast Server
/// Broadcast message to all connected clients
fn run_broadcast_server(address: &str) -> std::io::Result<()> {
let listener = TcpListener::bind(address)?;
println!("Broadcast server listening on {}", address);
let mut clients: Vec<TcpStream> = Vec::new();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
println!("Client connected");
clients.push(stream);
}
Err(e) => {
eprintln!("Error accepting connection: {}", e);
}
}
}
Ok(())
}
// Usage Examples
fn main() -> std::io::Result<()> {
println!("=== Web Rust TCP Socket Examples ===\n");
println!("Choose example:");
println!("1. Echo server");
println!("2. Echo client");
println!("3. Multi-threaded server");
println!("4. Chat server");
println!();
println!("Uncomment the example you want to run:");
println!("run_echo_server('127.0.0.1:8080')?;");
println!("run_echo_client('127.0.0.1:8080')?;");
println!("run_multi_threaded_server('127.0.0.1:8080')?;");
println!("run_chat_server('127.0.0.1:8080')?;");
// Example: Start echo server (commented out)
// run_echo_server("127.0.0.1:8080")?;
Ok(())
}