fix: shortening works!
Misunderstood RV, and was trying to convert the redis response to usize when it should be something compatible with "ok". () worked.
This commit is contained in:
parent
1993fa4893
commit
0349a5f465
115
src/main.rs
115
src/main.rs
|
@ -22,19 +22,51 @@ macro_rules! clone {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Validator, Clone)]
|
#[cfg(debug_assertions)]
|
||||||
#[validator(domain(ipv4(Allow), local(Allow), at_least_two_labels(Allow), port(Allow)))]
|
macro_rules! debuginfo {
|
||||||
struct Url {
|
($log:literal) => {
|
||||||
domain: String,
|
$log
|
||||||
port: Option<u16>,
|
};
|
||||||
|
($log:literal,$alt:literal) => {
|
||||||
|
$log
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Url {
|
#[cfg(not(debug_assertions))]
|
||||||
fn to_string(&self) -> String {
|
macro_rules! debuginfo {
|
||||||
match self.port {
|
($log:literal) => {
|
||||||
Some(port) => format!("{}:{}", self.domain, port),
|
"Internal error."
|
||||||
None => self.domain.clone(),
|
};
|
||||||
}
|
($log:literal,$alt:literal) => {
|
||||||
|
$alt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
macro_rules! ifdbg {
|
||||||
|
($expr:expr) => {
|
||||||
|
$expr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
macro_rules! ifdbg {
|
||||||
|
($expr:expr) => {
|
||||||
|
()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Validator)]
|
||||||
|
#[validator(http_url(local(Allow)))]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct HttpUrl {
|
||||||
|
url: validators::url::Url,
|
||||||
|
is_https: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for HttpUrl {
|
||||||
|
fn fmt(&self, f: &mut validators_prelude::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.url.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,13 +182,13 @@ enum AddResult {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum GetResult {
|
enum GetResult {
|
||||||
Found(Url),
|
Found(HttpUrl),
|
||||||
NotFound,
|
NotFound,
|
||||||
InternalError,
|
InternalError,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SlugDbMessage {
|
enum SlugDbMessage {
|
||||||
Add(Slug, Url, sync::oneshot::Sender<AddResult>),
|
Add(Slug, HttpUrl, sync::oneshot::Sender<AddResult>),
|
||||||
Get(Slug, sync::oneshot::Sender<GetResult>),
|
Get(Slug, sync::oneshot::Sender<GetResult>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,22 +243,23 @@ impl SlugDatabase {
|
||||||
response_channel.send(AddResult::Success(Slug(slug))).ok();
|
response_channel.send(AddResult::Success(Slug(slug))).ok();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(err) => {
|
||||||
response_channel.send(AddResult::Fail).ok();
|
response_channel.send(AddResult::Fail).ok();
|
||||||
|
ifdbg!(eprintln!("{}", err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {} // Ok(None); continue with insertion
|
_ => {} // Ok(None); continue with insertion
|
||||||
};
|
};
|
||||||
|
|
||||||
// The URL is not present in the database; insert it.
|
// The URL is not present in the database; insert it.
|
||||||
let add_result = connection.set_ex::<String, String, usize>(
|
let add_result = connection.set_ex::<String, String, ()>(
|
||||||
format!("slug:{}", requested_slug.0),
|
format!("slug:{}", requested_slug.0),
|
||||||
url_str.clone(),
|
url_str.clone(),
|
||||||
expire_seconds,
|
expire_seconds,
|
||||||
);
|
);
|
||||||
if add_result.is_ok() {
|
if add_result.is_ok() {
|
||||||
connection
|
connection
|
||||||
.set_ex::<String, String, usize>(
|
.set_ex::<String, String, ()>(
|
||||||
format!("url:{}", url_str),
|
format!("url:{}", url_str),
|
||||||
requested_slug.0.clone(),
|
requested_slug.0.clone(),
|
||||||
expire_seconds,
|
expire_seconds,
|
||||||
|
@ -236,7 +269,10 @@ impl SlugDatabase {
|
||||||
response_channel
|
response_channel
|
||||||
.send(match add_result {
|
.send(match add_result {
|
||||||
Ok(_) => AddResult::Success(requested_slug),
|
Ok(_) => AddResult::Success(requested_slug),
|
||||||
Err(_) => AddResult::Fail,
|
Err(err) => {
|
||||||
|
ifdbg!(eprintln!("{}", err));
|
||||||
|
AddResult::Fail
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.ok(); // If the receiver has hung up there's nothing we can do.
|
.ok(); // If the receiver has hung up there's nothing we can do.
|
||||||
}
|
}
|
||||||
|
@ -245,11 +281,14 @@ impl SlugDatabase {
|
||||||
connection.get(format!("slug:{}", slug.0));
|
connection.get(format!("slug:{}", slug.0));
|
||||||
match result {
|
match result {
|
||||||
Ok(Some(url)) => response_channel.send(GetResult::Found(
|
Ok(Some(url)) => response_channel.send(GetResult::Found(
|
||||||
Url::parse_string(url)
|
HttpUrl::parse_string(url)
|
||||||
.expect("Mismatched URL in the database."),
|
.expect("Mismatched URL in the database."),
|
||||||
)),
|
)),
|
||||||
Ok(None) => response_channel.send(GetResult::NotFound),
|
Ok(None) => response_channel.send(GetResult::NotFound),
|
||||||
Err(_) => response_channel.send(GetResult::InternalError),
|
Err(err) => {
|
||||||
|
ifdbg!(eprintln!("{}", err));
|
||||||
|
response_channel.send(GetResult::InternalError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.ok(); // If the receiver has hung up there's nothing we can do.
|
.ok(); // If the receiver has hung up there's nothing we can do.
|
||||||
}
|
}
|
||||||
|
@ -266,16 +305,16 @@ impl SlugDatabase {
|
||||||
fn insert_slug(
|
fn insert_slug(
|
||||||
&self,
|
&self,
|
||||||
requested_slug: Slug,
|
requested_slug: Slug,
|
||||||
url: Url,
|
url: HttpUrl,
|
||||||
) -> Result<sync::oneshot::Receiver<AddResult>, ()> {
|
) -> sync::oneshot::Receiver<AddResult> {
|
||||||
let (tx, rx) = sync::oneshot::channel();
|
let (tx, rx) = sync::oneshot::channel();
|
||||||
self.tx
|
self.tx
|
||||||
.send(SlugDbMessage::Add(requested_slug, url, tx))
|
.send(SlugDbMessage::Add(requested_slug, url, tx))
|
||||||
.expect("The SlugDbMessage channel is unexpectedly closed.");
|
.expect("The SlugDbMessage channel is unexpectedly closed.");
|
||||||
Ok(rx)
|
rx
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_slug(&self, slug: Slug) -> Result<Option<Url>, ()> {
|
async fn get_slug(&self, slug: Slug) -> Result<Option<HttpUrl>, ()> {
|
||||||
let (tx, rx) = sync::oneshot::channel();
|
let (tx, rx) = sync::oneshot::channel();
|
||||||
self.tx
|
self.tx
|
||||||
.send(SlugDbMessage::Get(slug, tx))
|
.send(SlugDbMessage::Get(slug, tx))
|
||||||
|
@ -353,40 +392,40 @@ async fn shorten(
|
||||||
base64::decode_config(b64str, base64::URL_SAFE_NO_PAD).map_err(|_| {
|
base64::decode_config(b64str, base64::URL_SAFE_NO_PAD).map_err(|_| {
|
||||||
(
|
(
|
||||||
warp::http::StatusCode::BAD_REQUEST,
|
warp::http::StatusCode::BAD_REQUEST,
|
||||||
"Invalid URL Base64.".into(),
|
debuginfo!("Could not decode base64 str.", "Invalid URL Base64.").into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let url_str = std::str::from_utf8(&unencoded_bytes[..]).map_err(|_| {
|
let url_str = std::str::from_utf8(&unencoded_bytes[..]).map_err(|_| {
|
||||||
(
|
(
|
||||||
warp::http::StatusCode::BAD_REQUEST,
|
warp::http::StatusCode::BAD_REQUEST,
|
||||||
"Invalid URL Base64.".into(),
|
debuginfo!(
|
||||||
|
"Parsed bytes of base64 str, but could not decode as UTF8.",
|
||||||
|
"Invalid URL Base64."
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
eprintln!("{}", url_str);
|
HttpUrl::parse_str(url_str)
|
||||||
Url::parse_str(url_str)
|
|
||||||
.map_err(|_| (warp::http::StatusCode::BAD_REQUEST, "Invalid URL.".into()))?
|
.map_err(|_| (warp::http::StatusCode::BAD_REQUEST, "Invalid URL.".into()))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_slug = slug_factory.generate();
|
let new_slug = slug_factory.generate();
|
||||||
let insert_result = db.insert_slug(new_slug, url);
|
let insert_result = db.insert_slug(new_slug, url).await;
|
||||||
match insert_result {
|
match insert_result {
|
||||||
Ok(receiver) => match receiver.await {
|
|
||||||
Ok(result) => match result {
|
Ok(result) => match result {
|
||||||
AddResult::Success(slug) => Ok(slug),
|
AddResult::Success(slug) => Ok(slug),
|
||||||
AddResult::Fail => Err((
|
AddResult::Fail => Err((
|
||||||
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
|
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Internal error.".into(),
|
debuginfo!("Got insertion response, but it was error.").into(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
Err(_) => Err((
|
Err(e) => {
|
||||||
|
ifdbg!(eprintln!("{}", e));
|
||||||
|
Err((
|
||||||
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
|
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Internal error.".into(),
|
debuginfo!("Receiver error on response of slug insertion.").into(),
|
||||||
)),
|
))
|
||||||
},
|
}
|
||||||
Err(()) => Err((
|
|
||||||
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
"Internal error.".into(),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue