Rust中實現使用者上傳功能的開源專案

banq發表於2024-04-03


此 Rust 專案演示了一個簡單的 PasteBin 應用程式的實現,其中使用 Actix 實現 Web 伺服器功能,使用 Rusqlite 進行資料庫操作,並使用 HTML 進行使用者介面。

它允許使用者提交文字內容,將其儲存在本地資料庫中,並使用生成的 URL 檢索它。

提供的 HTML 檔案定義了使用者介面的結構和設計,而 Rust 程式碼則處理 HTTP 請求、資料庫互動和 URL 路由。

什麼是PasteBin,為什麼是Rust?

  • PasteBin是一個簡單的線上服務,允許使用者上傳和共享文字或程式碼片段。它是開發人員快速共享程式碼或配置檔案的方便工具。
  • Rust以其安全性和效能而聞名,是Web服務的絕佳選擇。它提供了記憶體安全性,而無需垃圾收集器,使其適用於高效能Web應用程式。


執行應用程式:

  • 要執行該應用程式,請cargo run在終端中執行。
  • 透過導航至 來訪問 Web 瀏覽器中的應用程式http://localhost:8080。
  • 在文字區域中輸入所需的內容,然後單擊“提交”按鈕以生成用於貼上的 URL。
  • 與其他人共享生成的 URL 以訪問貼上內容。

依賴
請確保您的機器上安裝了Rust和Cargo。您還需要將以下依賴項新增到您的Cargo.toml檔案:

  • actix-web用於我們的Web伺服器和路由。
  • rusqlite用於SQLite資料庫互動。
  • rand用於為每個貼上生成唯一的令牌。
  • actix-files用於提供靜態檔案。
  • serde用於序列化和重新序列化資料。

[dependencies]
actix-web = <font>"3.0"
rusqlite = { version =
"0.29.0", features = ["bundled"] }
rand =
"0.8"
actix-files =
"0.5"
serde = { version =
"1.0", features = ["derive"] }

在 main.rs 中:

  • main.rs 主函式初始化我們的 SQLite 資料庫,並使用 Actix-web 設定網路伺服器。它將路由對映到處理程式,並啟動伺服器,在 localhost:8080 上監聽請求。
  • 當使用者提交貼上時,會使用 rand crate 生成一個唯一的標記。該標記作為貼上的識別符號,與貼上內容一起儲存在我們的 SQLite 資料庫中。
  • 檢索貼上內容非常簡單:我們在資料庫中查詢與 URL 中提供的標記相關聯的內容。如果找到,我們就會顯示;否則,我們就會顯示 "未找到貼上 "訊息。

詳細描述
1、匯入:
程式碼從 Actix、Rusqlite 和其他庫匯入必要的模組和特徵,以處理 HTTP 請求、資料庫操作並生成隨機令牌。

2、資料結構:
定義一個FormData結構體來表示從客戶端接收到的表單資料,以及一個AppState結構體來儲存資料庫連線。

FormDataStruct:讓我們定義一個結構體來表示從客戶端接收的表單資料。它將包括一個單獨的欄位content來儲存提交的內容。

#[derive(serde::Deserialize)]
struct FormData {
    content: String,
}

AppState :該結構用於儲存應用程式狀態,在本例中,是一個與 SQLite 資料庫的連線,該連線以 Mutex 封裝,用於跨執行緒安全訪問。

struct AppState {
    db: Mutex<Connection>,
}

3、main函式:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let db = Connection::open(<font>"pastes.db").expect("Failed to open database");

    db.execute(
       
"CREATE TABLE IF NOT EXISTS pastes (token TEXT PRIMARY KEY, content TEXT)",
        params![],
    )
    .expect(
"Failed to create table");

    let app_state = web::Data::new(AppState {
        db: Mutex::new(db),
    });

    HttpServer::new(move || {
        App::new()
            .app_data(app_state.clone())
            .service(web::resource(
"/style.css").to(|| {
                async { NamedFile::open(
"src/style.css") }
            }))
            .route(
"/", web::get().to(index))
            .route(
"/submit", web::post().to(submit))
            .route(
"/paste/{token}", web::get().to(get_paste))
    })
    .bind(
"127.0.0.1:8080")? // Binding the server to the specified address<i>
    .run()
    .await
// Starting the server and awaiting its completion<i>
}

這是程式的入口點。它執行以下任務:
  • 開啟或建立名為“pastes.db”的SQLite資料庫檔案。
  • 如果“pastes”表不存在,則建立該表,其中包含標記(主鍵)和內容列。
  • 使用資料庫連線定義應用程式狀態。
  • 配置Actix Web伺服器路由,包括提供靜態檔案(“/style.css”)、處理索引請求(“/”)、提交表單資料(“/submit”)和檢索貼上內容(“/paste/{token}”)。
  • 將伺服器繫結到地址“127.0.0.1:8080”並啟動伺服器。

4、路由處理程式:

  • index:處理對根URL(“/”)的GET請求並返回索引頁的HTML內容。為我們的 index.html 檔案提供服務,為使用者提供一個提交貼上內容的簡單表單。
  • submit:處理對“/submit”的POST請求,並使用隨機生成的令牌將提交的內容插入資料庫。為每個貼上生成一個唯一的標記,將其儲存在資料庫中,並將使用者重定向到其貼上的 URL。
  • get_paste:處理對“/paste/{token}”的 GET 請求,並從資料庫中檢索與提供的令牌關聯的內容。

async fn index() -> impl Responder { <font>// sends the response body for index.html<i>
    HttpResponse::Ok().body(include_str!(
"index.html"))
}

async fn submit(content: web::Form<FormData>, data: web::Data<AppState>) -> impl Responder {
// it takes some content<i>
    .
    .
    .
    .
}

async fn get_paste(token: web::Path<String>, data: web::Data<AppState>) -> impl Responder {
// this function helps to retrieve the value someone is sending to us<i>
    .
    .
    .
    .
}

5、資料庫操作:
開啟或建立名為“pastes.db”的 SQLite 資料庫檔案。
如果不存在,則建立一個名為“pastes”的表,其中包含標記(主鍵)和內容列。


6、Actix Web 伺服器配置:
配置 Actix Web 伺服器路由以提供靜態檔案(“/style.css”)和處理 HTTP 請求(“/”、“/submit”、“/paste/{token}”)。
將伺服器繫結到地址“127.0.0.1:8080”並啟動伺服器。

相關文章