diff --git a/Cargo.toml b/Cargo.toml index 9edcb13f..bffcb7b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,11 @@ parking_lot = "0.12.4" [dev-dependencies] tonic-build = { version = "0.12.3", features = ["prost"] } +[workspace] +members = [ + ".", +] + [features] default = ["download_snapshots", "serde", "generate-snippets"] download_snapshots = ["reqwest", "futures-util"] diff --git a/examples/web-integrations/.gitignore b/examples/web-integrations/.gitignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/examples/web-integrations/.gitignore @@ -0,0 +1 @@ +target diff --git a/examples/web-integrations/Cargo.toml b/examples/web-integrations/Cargo.toml new file mode 100644 index 00000000..c7e6277a --- /dev/null +++ b/examples/web-integrations/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "web-integrations-examples" +version = "0.1.0" +edition = "2021" +publish = false + +[workspace] + +[dependencies] +qdrant-client = { path = "../../", features = ["serde"] } +actix-web = "4.12.1" +axum = "0.8.7" +rocket = { version = "0.5.1", features = ["json"] } +serde_json = "1.0.128" +tokio = { version = "1.40.0", features = ["rt-multi-thread", "macros", "net"] } + +[[bin]] +name = "actix_web" +path = "src/actix_web.rs" + +[[bin]] +name = "axum" +path = "src/axum.rs" + +[[bin]] +name = "rocket" +path = "src/rocket.rs" diff --git a/examples/web-integrations/src/actix_web.rs b/examples/web-integrations/src/actix_web.rs new file mode 100644 index 00000000..33a17fc2 --- /dev/null +++ b/examples/web-integrations/src/actix_web.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; + +use actix_web::{web, App, HttpResponse, HttpServer, Responder}; +use qdrant_client::Qdrant; +use serde_json::json; + +struct AppState { + client: Arc, +} + +async fn list_collections(data: web::Data) -> impl Responder { + match data.client.list_collections().await { + Ok(collections) => { + let names: Vec = collections + .collections + .into_iter() + .map(|c| c.name) + .collect(); + HttpResponse::Ok().json(json!({ "collections": names })) + } + Err(e) => HttpResponse::InternalServerError().json(json!({ "error": e.to_string() })), + } +} + +async fn health_check(data: web::Data) -> impl Responder { + match data.client.health_check().await { + Ok(resp) => HttpResponse::Ok().json(json!({ "result": format!("{:?}", resp) })), + Err(e) => HttpResponse::InternalServerError().json(json!({ "error": e.to_string() })), + } +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + let client = Qdrant::from_url("http://localhost:6334") + .build() + .expect("Failed to create Qdrant client"); + + let state = web::Data::new(AppState { + client: Arc::new(client), + }); + + println!("Starting Actix server on http://localhost:8080"); + + HttpServer::new(move || { + App::new() + .app_data(state.clone()) + .route("/collections", web::get().to(list_collections)) + .route("/health", web::get().to(health_check)) + }) + .bind(("127.0.0.1", 8080))? + .run() + .await +} diff --git a/examples/web-integrations/src/axum.rs b/examples/web-integrations/src/axum.rs new file mode 100644 index 00000000..d125d140 --- /dev/null +++ b/examples/web-integrations/src/axum.rs @@ -0,0 +1,43 @@ +use std::sync::Arc; + +use axum::http::StatusCode; +use axum::routing::get; +use axum::{Json, Router}; +use qdrant_client::Qdrant; +use serde_json::{json, Value}; + +async fn list_collections( + axum::extract::State(client): axum::extract::State>, +) -> (StatusCode, Json) { + match client.list_collections().await { + Ok(collections) => { + let names: Vec = collections + .collections + .into_iter() + .map(|c| c.name) + .collect(); + (StatusCode::OK, Json(json!({ "collections": names }))) + } + Err(e) => ( + StatusCode::INTERNAL_SERVER_ERROR, + Json(json!({ "error": e.to_string() })), + ), + } +} + +#[tokio::main] +async fn main() { + let client = Qdrant::from_url("http://localhost:6334") + .build() + .expect("Failed to create Qdrant client"); + + let app = Router::new() + .route("/collections", get(list_collections)) + .with_state(Arc::new(client)); + + let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") + .await + .unwrap(); + println!("Starting Axum server on http://localhost:3000"); + axum::serve(listener, app).await.unwrap(); +} diff --git a/examples/web-integrations/src/rocket.rs b/examples/web-integrations/src/rocket.rs new file mode 100644 index 00000000..041f2b7e --- /dev/null +++ b/examples/web-integrations/src/rocket.rs @@ -0,0 +1,39 @@ +#[macro_use] +extern crate rocket; +use qdrant_client::Qdrant; +use rocket::http::Status; +use rocket::response::status; +use rocket::serde::json::Json; +use rocket::State; +use serde_json::{json, Value}; + +#[get("/collections")] +async fn list_collections( + client: &State, +) -> Result, status::Custom>> { + match client.list_collections().await { + Ok(collections) => { + let names: Vec = collections + .collections + .into_iter() + .map(|c| c.name) + .collect(); + Ok(Json(json!({ "collections": names }))) + } + Err(e) => Err(status::Custom( + Status::InternalServerError, + Json(json!({ "error": e.to_string() })), + )), + } +} + +#[launch] +async fn rocket() -> _ { + let client = Qdrant::from_url("http://localhost:6334") + .build() + .expect("Failed to create Qdrant client"); + + rocket::build() + .manage(client) + .mount("/", routes![list_collections]) +}