ผมเคยเจอปัญหา ConnectionError: timeout ตอนเรียก AI API ด้วย Rust ทุกที ประมาณ 2-3 ทุ่ม บริษัทต้องการเปลี่ยนจาก Python มาใช้ Rust เพื่อประสิทธิภาพสูงสุด แต่พอลอง deploy lamba ไปใช้งานจริง กลับได้ 401 Unauthorized ทุกครั้ง ทั้งที่ API key ถูกต้อง

วันนี้ผมจะสอนทุกขั้นตอนตั้งแต่ติดตั้ง ไปจนถึง production-ready code พร้อมวิธีแก้ Error ที่พบบ่อย 3 แบบ รวมถึงวิธีใช้ HolySheep AI ที่ให้ latency ต่ำกว่า 50ms และประหยัดกว่า 85%

ทำไมต้องใช้ Rust + reqwest + tokio?

เมื่อเทียบกับ Python หรือ Node.js การใช้ Rust กับ async runtime ช่วยให้:

Cargo.toml และ Dependency ที่จำเป็น

ก่อนเขียนโค้ด ต้องเพิ่ม dependency สำหรับ HTTP client และ JSON handling ก่อน

[dependencies]
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
tracing = "0.1"
tracing-subscriber = "0.3"

ใช้ rustls-tls แทน native-tls เพื่อหลีกเลี่ยงปัญหา OpenSSL บน Linux ที่ผมเจอตอน deploy บน AWS Lambda อยู่เยอะ

โครงสร้างโปรเจกต์ Rust สำหรับ AI API Call

สร้างโครงสร้างโฟลเดอร์แบบ standard project layout จะช่วยให้ maintain และ test ได้ง่าย

src/
├── main.rs
├── api/
│   ├── mod.rs
│   └── holysheep.rs
├── models/
│   ├── mod.rs
│   └── chat.rs
└── error.rs

โค้ดหลัก: Chat Completion กับ HolySheep AI

use anyhow::Result;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::time::Duration;

// ===== Models =====
#[derive(Debug, Serialize)]
struct ChatRequest {
    model: String,
    messages: Vec,
    temperature: Option,
    max_tokens: Option,
}

#[derive(Debug, Serialize, Clone)]
struct Message {
    role: String,
    content: String,
}

#[derive(Debug, Deserialize)]
struct ChatResponse {
    id: String,
    choices: Vec,
    usage: Usage,
}

#[derive(Debug, Deserialize)]
struct Choice {
    message: ResponseMessage,
    finish_reason: String,
}

#[derive(Debug, Deserialize)]
struct ResponseMessage {
    role: String,
    content: String,
}

#[derive(Debug, Deserialize)]
struct Usage {
    prompt_tokens: u32,
    completion_tokens: u32,
    total_tokens: u32,
}

// ===== HolySheep API Client =====
pub struct HolySheepClient {
    client: Client,
    api_key: String,
    base_url: String,
}

impl HolySheepClient {
    pub fn new(api_key: &str) -> Self {
        let client = Client::builder()
            .timeout(Duration::from_secs(30)) // แก้ timeout error
            .connect_timeout(Duration::from_secs(10))
            .build()
            .expect("Failed to create HTTP client");

        Self {
            client,
            api_key: api_key.to_string(),
            base_url: "https://api.holysheep.ai/v1".to_string(),
        }
    }

    pub async fn chat_completion(
        &self,
        model: &str,
        messages: Vec,
    ) -> Result {
        let url = format!("{}/chat/completions", self.base_url);
        
        let request = ChatRequest {
            model: model.to_string(),
            messages,
            temperature: Some(0.7),
            max_tokens: Some(2048),
        };

        let response = self.client
            .post(&url)
            .header("Authorization", format!("Bearer {}", self.api_key))
            .header("Content-Type", "application/json")
            .json(&request)
            .send()
            .await?;

        // ตรวจสอบ status code ก่อน parse
        let status = response.status();
        if !status.is_success() {
            let error_body = response.text().await?;
            anyhow::bail!("API Error {}: {}", status, error_body);
        }

        let chat_response = response.json::().await?;
        Ok(chat_response)
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    // อ่าน API key จาก environment variable
    let api_key = std::env::var("HOLYSHEEP_API_KEY")
        .expect("HOLYSHEEP_API_KEY must be set");

    let client = HolySheepClient::new(&api_key);

    let messages = vec![
        Message {
            role: "system".to_string(),
            content: "คุณเป็นผู้ช่วย AI ที่เป็นมิตร".to_string(),
        },
        Message {
            role: "user".to_string(),
            content: "สวัสดี บอกข้อมูลราคาของ HolySheep AI หน่อย".to_string(),
        },
    ];

    let response = client.chat_completion("gpt-4.1", messages).await?;
    
    println!("Response ID: {}", response.id);
    println!("Content: {}", response.choices[0].message.content);
    println!("Tokens used: {}", response.usage.total_tokens);

    Ok(())
}

โค้ดนี้ใช้ HolySheep AI ที่ให้บริการ API ราคาถูกกว่า 85% เมื่อเทียบกับ OpenAI โดยมีราคา GPT-4.1 $8/MTok, Claude Sonnet 4.5 $15/MTok และ DeepSeek V3.2 เพียง $0.42/MTok เท่านั้น รองรับ WeChat และ Alipay พร้อม latency ต่ำกว่า 50ms

Batch Request หลาย ๆ คำถามพร้อมกัน

สำหรับงานที่ต้องถาม AI หลายคำถาม ใช้ futures เพื่อทำ concurrent request และใช้ประโยชน์จาก async ได้เต็มที่

use futures::future::join_all;

async fn batch_chat(
    client: &HolySheepClient,
    questions: Vec<&str>,
    model: &str,
) -> Result> {
    let futures: Vec<_> = questions
        .iter()
        .map(|q| {
            let messages = vec![Message {
                role: "user".to_string(),
                content: q.to_string(),
            }];
            client.chat_completion(model, messages)
        })
        .collect();

    let results = join_all(futures).await;
    
    results
        .into_iter()
        .map(|r| {
            let response = r?;
            Ok(response.choices[0].message.content.clone())
        })
        .collect()
}

#[tokio::main]
async fn main() -> Result<()> {
    let api_key = std::env::var("HOLYSHEEP_API_KEY")?;
    let client = HolySheepClient::new(&api_key);

    let questions = vec![
        "สร้าง function sum ใน Rust",
        "วิธีติดตั้ง Rust บน Ubuntu",
        "async/await คืออะไร",
    ];

    let answers = batch_chat(&client, questions, "gpt-4.1").await?;

    for (q, a) in questions.iter().zip(answers.iter()) {
        println!("Q: {}\nA: {}\n", q, a);
    }

    Ok(())
}

ต้องเพิ่ม futures = "0.3" ใน Cargo.toml ด้วย

การตั้งค่า Environment Variables และ Error Handling

// src/error.rs
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ApiError {
    #[error("HTTP request failed: {0}")]
    RequestFailed(#[from] reqwest::Error),
    
    #[error("API returned error: {status} - {message}")]
    ApiResponse { status: u16, message: String },
    
    #[error("Authentication failed: invalid API key")]
    AuthFailed,
    
    #[error("Rate limit exceeded: retry after {0} seconds")]
    RateLimited(u64),
    
    #[error("Invalid request: {0}")]
    InvalidRequest(String),
}

impl From for ApiError {
    fn from(response: Response) -> Self {
        let status = response.status().as_u16();
        match status {
            401 => ApiError::AuthFailed,
            429 => ApiError::RateLimited(60), // default retry after
            400..=499 => ApiError::InvalidRequest(format!("HTTP {}", status)),
            500..=599 => ApiError::ApiResponse {
                status,
                message: "Server error".to_string(),
            },
            _ => ApiError::ApiResponse {
                status,
                message: "Unknown error".to_string(),
            },
        }
    }
}

เพิ่ม thiserror = "1.0" ใน dependency จะช่วยให้ error handling ดู professional และ trace ได้ง่าย

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. Error 401 Unauthorized — API Key ไม่ถูกต้อง

อาการ: ได้รับ error {"error": {"message": "Invalid authentication", "type": "invalid_request_error"}}

สาเหตุ: Header Authorization ไม่ถูกต้อง หรือ API key หมดอายุ หรือใช้ base_url ผิด

// ❌ วิธีผิด — ใช้ OpenAI endpoint
let url = "https://api.openai.com/v1/chat/completions";

// ✅ วิธีถูก — ใช้ HolySheep endpoint
let base_url = "https://api.holysheep.ai/v1";
let url = format!("{}/chat/completions", base_url);

// ✅ Header ต้องมี Bearer prefix
.header("Authorization", format!("Bearer {}", api_key))

2. Connection Timeout — เน็ตเวิร์กช้าหรือ API ตอบสนองช้า

อาการ: reqwest::Error { kind: Request, url: "...", source: "connection timed out" }

สาเหตุ: Server ไกลเกินไป หรือ API ประมวลผลนานเกิน default timeout

// แก้ไขด้วยการเพิ่ม timeout ที่เหมาะสม
let client = Client::builder()
    .timeout(Duration::from_secs(60)) // request timeout
    .connect_timeout(Duration::from_secs(15)) // connection timeout
    .pool_max_idle_per_host(10) // connection reuse
    .build()?;

// ใช้ HolySheep ที่ latency < 50ms จะช่วยลด timeout ลงมาก
// สมัครที่: https://www.holysheep.ai/register

3. JSON Parse Error — Response ไม่ตรง format

อาการ: reqwest::Error { kind: Json, ... } หรือ expected value at line 1 column 1

สาเหตุ: Model field ผิด หรือ API คืน error message แทน JSON ปกติ

// แก้ไขด้วยการ debug response ก่อน parse
let response = self.client
    .post(&url)
    .json(&request)
    .send()
    .await?;

let status = response.status();
let body = response.text().await?;

tracing::debug!("Response status: {}, body: {}", status, body);

if !status.is_success() {
    // Parse error response แยก
    if let Ok(error_resp) = serde_json::from_str::(&body) {
        let message = error_resp["error"]["message"]
            .as_str()
            .unwrap_or("Unknown error");
        anyhow::bail!("API Error {}: {}", status, message);
    }
    anyhow::bail!("Unexpected error response: {}", body);
}

let chat_response: ChatResponse = serde_json::from_str(&body)?;

4. TLS/SSL Error — Certificate verification failed

อาการ: rustls::client::verify_server_certificates` failed: Custom { kind: InvalidData, error: BadDER }

สาเหตุ: OpenSSL บน Linux server ไม่รองรับ หรือ corporate proxy ตัด SSL

// ใช้ rustls แทน native-tls ใน Cargo.toml
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }

// และปิด certificate verification (สำหรับ development เท่านั้น)
let client = Client::builder()
    .danger_accept_invalid_certs(true) // ⚠️ ใช้เฉพาะ dev
    .build()?;

สรุป

การใช้ Rust reqwest กับ tokio เพื่อเรียก AI API ต้องระวังเรื่อง timeout, authentication header และ JSON parsing error เป็นหลัก การใช้ HolySheep AI ช่วยลดปัญหา latency ได้มากเพราะมี response time ต่ำกว่า 50ms รวมถึงราคาที่ประหยัดกว่า 85% เมื่อเทียบกับ OpenAI

ถ้าต้องการ production deployment ลองใช้ Docker container กับ Alpine Linux จะช่วยลด image size และปัญหา dependency ได้ดี

👉 สมัคร HolySheep AI — รับเครดิตฟรีเมื่อลงทะเบียน