v0.07
This commit is contained in:
142
backend/api/src/lib.rs
Normal file
142
backend/api/src/lib.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
use axum::{
|
||||
http::{HeaderValue, Method},
|
||||
response::IntoResponse,
|
||||
routing::get,
|
||||
Json, Router,
|
||||
};
|
||||
use axum_extra::routing::SpaRouter;
|
||||
use clap::Parser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::cors::CorsLayer;
|
||||
use tower_http::trace::TraceLayer;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct Docs {
|
||||
key: String,
|
||||
title: String,
|
||||
first_publish_year: Option<u32>,
|
||||
number_of_pages_median: Option<u32>,
|
||||
isbn: Option<Vec<String>>,
|
||||
cover_i: Option<u32>,
|
||||
cover_url: Option<String>,
|
||||
author_name: Option<Vec<String>>,
|
||||
person: Option<Vec<String>>,
|
||||
place: Option<Vec<String>>,
|
||||
subject: Option<Vec<String>>,
|
||||
time: Option<Vec<String>>,
|
||||
}
|
||||
/*
|
||||
impl Docs {
|
||||
fn set_cover_url(&mut self) {
|
||||
match self.cover_i {
|
||||
Some(cover_i) => {
|
||||
self.cover_url = Some(format!(
|
||||
"https://covers.openlibrary.org/b/id/{}-L.jpg",
|
||||
(cover_i.unwrap())
|
||||
))
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct Books {
|
||||
num_found: u32,
|
||||
docs: Vec<Docs>,
|
||||
}
|
||||
|
||||
impl Books {
|
||||
fn set_all_cover_urls(&mut self) {
|
||||
for book in self.docs.iter_mut() {
|
||||
match book.cover_i {
|
||||
Some(cover_i) => {
|
||||
book.cover_url = Some(format!(
|
||||
"https://covers.openlibrary.org/b/id/{}-L.jpg",
|
||||
cover_i
|
||||
))
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the command line interface with clap.
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "server", about = "A server for our wasm project!")]
|
||||
struct Opt {
|
||||
/// set the log level
|
||||
#[clap(short = 'l', long = "log", default_value = "debug")]
|
||||
log_level: String,
|
||||
|
||||
/// set the listen addr
|
||||
#[clap(short = 'a', long = "addr", default_value = "::1")]
|
||||
addr: String,
|
||||
|
||||
/// set the listen port
|
||||
#[clap(short = 'p', long = "port", default_value = "8081")]
|
||||
port: u16,
|
||||
|
||||
/// set the directory where static files are to be found
|
||||
#[clap(long = "static-dir", default_value = "../dist")]
|
||||
static_dir: String,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
let opt = Opt::parse();
|
||||
|
||||
// Setup logging & RUST_LOG from args
|
||||
if std::env::var("RUST_LOG").is_err() {
|
||||
std::env::set_var("RUST_LOG", format!("{},hyper=info,mio=info", opt.log_level))
|
||||
}
|
||||
// enable console logging
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let app = Router::new()
|
||||
.route("/api/hello", get(hello))
|
||||
.merge(SpaRouter::new("/assets", opt.static_dir))
|
||||
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()))
|
||||
.layer(
|
||||
// see https://docs.rs/tower-http/latest/tower_http/cors/index.html
|
||||
// for more details
|
||||
//
|
||||
// pay attention that for some request types like posting content-type: application/json
|
||||
// it is required to add ".allow_headers([http::header::CONTENT_TYPE])"
|
||||
// or see this issue https://github.com/tokio-rs/axum/issues/849
|
||||
CorsLayer::new()
|
||||
.allow_origin("http://localhost:8080".parse::<HeaderValue>().unwrap())
|
||||
.allow_methods([Method::GET]),
|
||||
);
|
||||
|
||||
let sock_addr = SocketAddr::from((
|
||||
IpAddr::from_str(opt.addr.as_str()).unwrap_or(IpAddr::V6(Ipv6Addr::LOCALHOST)),
|
||||
opt.port,
|
||||
));
|
||||
|
||||
log::info!("listening on http://{}", sock_addr);
|
||||
|
||||
axum::Server::bind(&sock_addr)
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.expect("Unable to start server");
|
||||
}
|
||||
|
||||
async fn hello(
|
||||
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
print!("Get items with query params: {:?}\n", params);
|
||||
let search = params.get("search").unwrap();
|
||||
let query = format!("https://openlibrary.org/search.json?q={}", search);
|
||||
let res = reqwest::get(query).await.expect("Unable to request");
|
||||
let mut resjson = res.json::<Books>().await.expect("Unable to return value");
|
||||
resjson.docs.truncate(10);
|
||||
resjson.set_all_cover_urls();
|
||||
print!("Search token {:?}\n", search);
|
||||
return Json(resjson);
|
||||
}
|
||||
Reference in New Issue
Block a user