Skip to content

Commit c0f35a8

Browse files
author
qtfkwk
committed
1 parent 84ca2d7 commit c0f35a8

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ futures-util = "0.3"
3535
futures = "0.3"
3636
walkdir = "2.3"
3737
toml_edit = {version = "0.14", features = ["easy"] }
38+
panamax-search-lib = { path = "../../../dev/panamax-search/crates/lib" }
3839

3940
[features]
4041
default = []

src/serve.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use std::{collections::HashMap, io, net::SocketAddr, path::PathBuf, process::Stdio};
1+
use std::{collections::HashMap, io, net::SocketAddr, path::{Path, PathBuf}, process::Stdio};
22

33
use askama::Template;
44
use bytes::BytesMut;
55
use futures_util::stream::TryStreamExt;
66
use include_dir::{include_dir, Dir};
7+
use panamax_search_lib::Index;
8+
use serde::{Deserialize, Serialize};
79
use thiserror::Error;
810
use tokio::{
911
fs::File,
@@ -57,6 +59,56 @@ pub enum ServeError {
5759

5860
impl Reject for ServeError {}
5961

62+
#[derive(Deserialize)]
63+
struct CratesSearch {
64+
q: String,
65+
per_page: usize,
66+
}
67+
68+
async fn search(p: &CratesSearch, path: &Path) -> Result<http::Response<String>, Rejection> {
69+
if let Ok(index) = Index::load(path) {
70+
let crates = index
71+
.search(&[p.q.clone()], true)
72+
.to_vec()
73+
.into_iter()
74+
.map(|crate_| Crate {
75+
name: crate_.name,
76+
description: crate_.description,
77+
max_version: if let Some(v) = &crate_.latest_ny {
78+
v.to_string()
79+
} else {
80+
String::from("0.0.0")
81+
},
82+
})
83+
.collect::<Vec<_>>();
84+
let meta = TotalCrates { total: crates.len() as u32 };
85+
let crates = Crates { crates, meta };
86+
let body = serde_json::to_string(&crates).unwrap();
87+
if let Ok(res) = Response::builder().body(body) {
88+
return Ok(res);
89+
}
90+
}
91+
Err(warp::reject::not_found())
92+
}
93+
94+
#[derive(Serialize)]
95+
struct Crate {
96+
name: String,
97+
description: Option<String>,
98+
max_version: String,
99+
}
100+
101+
#[derive(Serialize)]
102+
struct TotalCrates {
103+
total: u32,
104+
}
105+
106+
#[derive(Serialize)]
107+
struct Crates {
108+
crates: Vec<Crate>,
109+
meta: TotalCrates,
110+
}
111+
60112
pub async fn serve(path: PathBuf, socket_addr: SocketAddr, tls_paths: Option<TlsConfig>) {
61113
let index_path = path.clone();
62114
let is_tls = tls_paths.is_some();
@@ -84,6 +136,15 @@ pub async fn serve(path: PathBuf, socket_addr: SocketAddr, tls_paths: Option<Tls
84136
},
85137
);
86138

139+
// Handle `cargo search` queries ("/crates?q={}&per_page={}")
140+
let search_path = path.clone();
141+
let crates_search = warp::path::path("crates")
142+
.and(warp::query::<CratesSearch>())
143+
.and_then(move |p: CratesSearch| {
144+
let path = search_path.clone();
145+
async move { search(&p, &path).await }
146+
});
147+
87148
// Handle all files baked into the binary with include_dir, at /static
88149
let static_dir =
89150
warp::path::path("static")
@@ -190,6 +251,7 @@ pub async fn serve(path: PathBuf, socket_addr: SocketAddr, tls_paths: Option<Tls
190251
.or(static_dir)
191252
.or(dist_dir)
192253
.or(rustup_dir)
254+
.or(crates_search)
193255
.or(crates_dir_native_format)
194256
.or(crates_dir_condensed_format)
195257
.or(sparse_index)

0 commit comments

Comments
 (0)