diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 56 |
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 @@ | |||
1 | use futures_util::TryStreamExt; | 1 | use anyhow::{Context, Result}; |
2 | use hyper::service::{make_service_fn, service_fn}; | 2 | use hyper::service::{make_service_fn, service_fn}; |
3 | use hyper::{Body, Method, Request, Response, Server, StatusCode}; | 3 | use hyper::{Body, Method, Request, Response, Server, StatusCode}; |
4 | use nanoid::nanoid; | 4 | use nanoid::nanoid; |
5 | use rusqlite::{params, Connection, OpenFlags, Result, NO_PARAMS}; | 5 | use rusqlite::{params, Connection, OpenFlags, NO_PARAMS}; |
6 | use url::form_urlencoded; | 6 | use url::form_urlencoded; |
7 | 7 | ||
8 | use std::collections::HashMap; | 8 | use std::collections::HashMap; |
9 | use std::path::{Path, PathBuf}; | 9 | use std::path::Path; |
10 | use std::str::from_utf8; | ||
11 | 10 | ||
12 | fn shorten<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<String> { | 11 | fn 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 | ||
27 | fn get_link<S: AsRef<str>>(url: S, conn: &mut Connection) -> Result<Option<String>> { | 26 | fn 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 | ||
39 | async fn shortner_service(req: Request<Body>) -> Result<Response<Body>, hyper::Error> { | 37 | async 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 | } |