aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-08-23 06:08:49 +0100
committerAkshay <[email protected]>2020-08-23 06:08:49 +0100
commit4c19a73fd1d21fb5d40cf15cb7312e37502bc03a (patch)
tree47d4858e66d9519df38ea9d60cbdff1a0529aac3
parent70eeba1f481d625db311ea4d961453d3e1b90ea7 (diff)
add basic error handling
-rw-r--r--src/main.rs56
1 files changed, 40 insertions, 16 deletions
diff --git a/src/main.rs b/src/main.rs
index 801da3c..cb76d5b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,19 +1,18 @@
1use futures_util::TryStreamExt; 1use anyhow::{Context, Result};
2use hyper::service::{make_service_fn, service_fn}; 2use hyper::service::{make_service_fn, service_fn};
3use hyper::{Body, Method, Request, Response, Server, StatusCode}; 3use hyper::{Body, Method, Request, Response, Server, StatusCode};
4use nanoid::nanoid; 4use nanoid::nanoid;
5use rusqlite::{params, Connection, OpenFlags, Result, NO_PARAMS}; 5use rusqlite::{params, Connection, OpenFlags, NO_PARAMS};
6use url::form_urlencoded; 6use url::form_urlencoded;
7 7
8use std::collections::HashMap; 8use std::collections::HashMap;
9use std::path::{Path, PathBuf}; 9use std::path::Path;
10use std::str::from_utf8;
11 10
12fn shorten<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<String> { 11fn shorten<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<String> {
13 let mut stmt = conn.prepare("select * from urls where link = ?1")?; 12 let mut stmt = conn.prepare("select * from urls where link = ?1")?;
14 let mut rows = stmt.query(params![url.as_ref().to_string()])?; 13 let mut rows = stmt.query(params![url.as_ref().to_string()])?;
15 if let Some(row) = rows.next()? { 14 if let Some(row) = rows.next()? {
16 return row.get(1); 15 return Ok(row.get(1)?);
17 } else { 16 } else {
18 let new_id = nanoid!(4); 17 let new_id = nanoid!(4);
19 conn.execute( 18 conn.execute(
@@ -25,7 +24,6 @@ fn shorten<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<String> {
25} 24}
26 25
27fn get_link<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<Option<String>> { 26fn get_link<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<Option<String>> {
28 eprintln!("{}", url.as_ref());
29 let url = url.as_ref(); 27 let url = url.as_ref();
30 let mut stmt = conn.prepare("select * from urls where shortlink = ?1")?; 28 let mut stmt = conn.prepare("select * from urls where shortlink = ?1")?;
31 let mut rows = stmt.query(params![url.to_string()])?; 29 let mut rows = stmt.query(params![url.to_string()])?;
@@ -36,33 +34,59 @@ fn get_link<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<Option<Strin
36 } 34 }
37} 35}
38 36
39async fn shortner_service(req: Request<Body>) -> Result<Response<Body>, hyper::Error> { 37async fn shortner_service(req: Request<Body>) -> Result<Response<Body>> {
40 let mut conn = init_db("./urls.db_3").unwrap(); 38 let mut conn = init_db("./urls.db_3").unwrap();
39 eprintln!("{:?}", req);
41 40
42 match req.method() { 41 match req.method() {
43 &Method::POST => { 42 &Method::POST => {
44 let b = hyper::body::to_bytes(req).await?; 43 let b = hyper::body::to_bytes(req)
44 .await
45 .with_context(|| format!("Failed to stream request body!"))?;
46
45 let params = form_urlencoded::parse(b.as_ref()) 47 let params = form_urlencoded::parse(b.as_ref())
46 .into_owned() 48 .into_owned()
47 .collect::<HashMap<String, String>>(); 49 .collect::<HashMap<String, String>>();
48 50
49 if let Some(n) = params.get("shorten") { 51 if let Some(n) = params.get("shorten") {
50 let shortlink = shorten(n, &mut conn).unwrap(); 52 let shortlink = shorten(n, &mut conn)?;
51 return Ok(Response::new(Body::from(shortlink))); 53 eprintln!("{}", shortlink);
54 let res = Response::builder()
55 .status(StatusCode::OK)
56 .header("content-type", "text/html")
57 .body(Body::from(shortlink))?;
58 Ok(res)
52 } else { 59 } else {
53 return Ok(Response::new(Body::from("invalid form"))); 60 eprintln!("hello world");
54 }; 61 let res = Response::builder()
62 .status(StatusCode::UNPROCESSABLE_ENTITY)
63 .body(Body::empty())?;
64 Ok(res)
65 }
55 } 66 }
56 &Method::GET => { 67 &Method::GET => {
57 let shortlink = req.uri().path().to_string(); 68 let shortlink = req.uri().path().to_string();
58 let link = get_link(&shortlink[1..], &mut conn); 69 let link = get_link(&shortlink[1..], &mut conn);
59 if let Some(l) = link.unwrap() { 70 if let Some(l) = link.unwrap() {
60 return Ok(Response::new(Body::from(l))); 71 Ok(Response::builder()
72 .header("Location", &l)
73 .header("content-type", "text/html")
74 .status(StatusCode::MOVED_PERMANENTLY)
75 .body(Body::from(format!(
76 "You will be redirected to: {}. If not, click the link.",
77 &l
78 )))?)
61 } else { 79 } else {
62 return Ok(Response::new(Body::from("not found!"))); 80 Ok(Response::builder()
81 .status(StatusCode::NOT_FOUND)
82 .body(Body::empty())?)
63 } 83 }
64 } 84 }
65 _ => unimplemented!(), 85 _ => {
86 return Ok(Response::builder()
87 .status(StatusCode::NOT_FOUND)
88 .body(Body::empty())?)
89 }
66 } 90 }
67} 91}
68 92
@@ -76,7 +100,7 @@ fn init_db<P: AsRef<Path>>(p: P) -> Result<Connection> {
76 link TEXT PRIMARY KEY, 100 link TEXT PRIMARY KEY,
77 shortlink TEXT NOT NULL 101 shortlink TEXT NOT NULL
78 )", 102 )",
79 params![], 103 NO_PARAMS,
80 )?; 104 )?;
81 return Ok(conn); 105 return Ok(conn);
82} 106}