diff options
-rw-r--r-- | Cargo.lock | 69 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/db.rs | 8 | ||||
-rw-r--r-- | src/main.rs | 4 | ||||
-rw-r--r-- | src/service.rs | 14 |
5 files changed, 91 insertions, 6 deletions
@@ -72,6 +72,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
72 | checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" | 72 | checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" |
73 | 73 | ||
74 | [[package]] | 74 | [[package]] |
75 | name = "atty" | ||
76 | version = "0.2.14" | ||
77 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
78 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | ||
79 | dependencies = [ | ||
80 | "hermit-abi", | ||
81 | "libc", | ||
82 | "winapi 0.3.9", | ||
83 | ] | ||
84 | |||
85 | [[package]] | ||
75 | name = "autocfg" | 86 | name = "autocfg" |
76 | version = "0.1.7" | 87 | version = "0.1.7" |
77 | source = "registry+https://github.com/rust-lang/crates.io-index" | 88 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -171,6 +182,19 @@ dependencies = [ | |||
171 | ] | 182 | ] |
172 | 183 | ||
173 | [[package]] | 184 | [[package]] |
185 | name = "env_logger" | ||
186 | version = "0.7.1" | ||
187 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
188 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" | ||
189 | dependencies = [ | ||
190 | "atty", | ||
191 | "humantime", | ||
192 | "log", | ||
193 | "regex", | ||
194 | "termcolor", | ||
195 | ] | ||
196 | |||
197 | [[package]] | ||
174 | name = "event-listener" | 198 | name = "event-listener" |
175 | version = "2.4.0" | 199 | version = "2.4.0" |
176 | source = "registry+https://github.com/rust-lang/crates.io-index" | 200 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -366,8 +390,10 @@ version = "0.1.0" | |||
366 | dependencies = [ | 390 | dependencies = [ |
367 | "anyhow", | 391 | "anyhow", |
368 | "hyper", | 392 | "hyper", |
393 | "log", | ||
369 | "multer", | 394 | "multer", |
370 | "nanoid", | 395 | "nanoid", |
396 | "pretty_env_logger", | ||
371 | "rusqlite", | 397 | "rusqlite", |
372 | "smol", | 398 | "smol", |
373 | "url", | 399 | "url", |
@@ -410,6 +436,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
410 | checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" | 436 | checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" |
411 | 437 | ||
412 | [[package]] | 438 | [[package]] |
439 | name = "humantime" | ||
440 | version = "1.3.0" | ||
441 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
442 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" | ||
443 | dependencies = [ | ||
444 | "quick-error", | ||
445 | ] | ||
446 | |||
447 | [[package]] | ||
413 | name = "hyper" | 448 | name = "hyper" |
414 | version = "0.13.7" | 449 | version = "0.13.7" |
415 | source = "registry+https://github.com/rust-lang/crates.io-index" | 450 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -709,6 +744,16 @@ dependencies = [ | |||
709 | ] | 744 | ] |
710 | 745 | ||
711 | [[package]] | 746 | [[package]] |
747 | name = "pretty_env_logger" | ||
748 | version = "0.4.0" | ||
749 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
750 | checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" | ||
751 | dependencies = [ | ||
752 | "env_logger", | ||
753 | "log", | ||
754 | ] | ||
755 | |||
756 | [[package]] | ||
712 | name = "proc-macro-hack" | 757 | name = "proc-macro-hack" |
713 | version = "0.5.18" | 758 | version = "0.5.18" |
714 | source = "registry+https://github.com/rust-lang/crates.io-index" | 759 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -730,6 +775,12 @@ dependencies = [ | |||
730 | ] | 775 | ] |
731 | 776 | ||
732 | [[package]] | 777 | [[package]] |
778 | name = "quick-error" | ||
779 | version = "1.2.3" | ||
780 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
781 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" | ||
782 | |||
783 | [[package]] | ||
733 | name = "quote" | 784 | name = "quote" |
734 | version = "1.0.7" | 785 | version = "1.0.7" |
735 | source = "registry+https://github.com/rust-lang/crates.io-index" | 786 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -951,6 +1002,15 @@ dependencies = [ | |||
951 | ] | 1002 | ] |
952 | 1003 | ||
953 | [[package]] | 1004 | [[package]] |
1005 | name = "termcolor" | ||
1006 | version = "1.1.0" | ||
1007 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1008 | checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" | ||
1009 | dependencies = [ | ||
1010 | "winapi-util", | ||
1011 | ] | ||
1012 | |||
1013 | [[package]] | ||
954 | name = "thread_local" | 1014 | name = "thread_local" |
955 | version = "1.0.1" | 1015 | version = "1.0.1" |
956 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1156,6 +1216,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1156 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | 1216 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
1157 | 1217 | ||
1158 | [[package]] | 1218 | [[package]] |
1219 | name = "winapi-util" | ||
1220 | version = "0.1.5" | ||
1221 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1222 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | ||
1223 | dependencies = [ | ||
1224 | "winapi 0.3.9", | ||
1225 | ] | ||
1226 | |||
1227 | [[package]] | ||
1159 | name = "winapi-x86_64-pc-windows-gnu" | 1228 | name = "winapi-x86_64-pc-windows-gnu" |
1160 | version = "0.4.0" | 1229 | version = "0.4.0" |
1161 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -13,6 +13,8 @@ nanoid = "0.3.0" | |||
13 | url = "2.1.1" | 13 | url = "2.1.1" |
14 | anyhow = "1.0" | 14 | anyhow = "1.0" |
15 | multer = "1.2" | 15 | multer = "1.2" |
16 | log = "0.4" | ||
17 | pretty_env_logger = "0.4.0" | ||
16 | 18 | ||
17 | 19 | ||
18 | [dependencies.smol] | 20 | [dependencies.smol] |
@@ -1,11 +1,14 @@ | |||
1 | use anyhow::Result; | 1 | use anyhow::Result; |
2 | use log::{debug, info}; | ||
2 | use rusqlite::{Connection, OpenFlags, NO_PARAMS}; | 3 | use rusqlite::{Connection, OpenFlags, NO_PARAMS}; |
3 | 4 | ||
5 | use std::fmt; | ||
4 | use std::path::Path; | 6 | use std::path::Path; |
5 | 7 | ||
6 | pub fn init_db<P: AsRef<Path>>(p: P) -> Result<Connection> { | 8 | pub fn init_db<P: AsRef<Path> + fmt::Display>(p: P) -> Result<Connection> { |
9 | debug!("Looking for database at `{}`", p); | ||
7 | let conn = Connection::open_with_flags( | 10 | let conn = Connection::open_with_flags( |
8 | p, | 11 | &p, |
9 | OpenFlags::SQLITE_OPEN_CREATE | OpenFlags::SQLITE_OPEN_READ_WRITE, | 12 | OpenFlags::SQLITE_OPEN_CREATE | OpenFlags::SQLITE_OPEN_READ_WRITE, |
10 | )?; | 13 | )?; |
11 | conn.execute( | 14 | conn.execute( |
@@ -15,5 +18,6 @@ pub fn init_db<P: AsRef<Path>>(p: P) -> Result<Connection> { | |||
15 | )", | 18 | )", |
16 | NO_PARAMS, | 19 | NO_PARAMS, |
17 | )?; | 20 | )?; |
21 | info!("SQLite3 database `{}` initialized", &p); | ||
18 | return Ok(conn); | 22 | return Ok(conn); |
19 | } | 23 | } |
diff --git a/src/main.rs b/src/main.rs index d31abfe..6b48957 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,18 +1,20 @@ | |||
1 | use anyhow::Result; | 1 | use anyhow::Result; |
2 | use hyper::service::{make_service_fn, service_fn}; | 2 | use hyper::service::{make_service_fn, service_fn}; |
3 | use hyper::Server; | 3 | use hyper::Server; |
4 | use log::trace; | ||
4 | 5 | ||
5 | mod db; | 6 | mod db; |
6 | mod service; | 7 | mod service; |
7 | use service::shortner_service; | 8 | use service::shortner_service; |
8 | 9 | ||
9 | fn main() -> Result<()> { | 10 | fn main() -> Result<()> { |
11 | pretty_env_logger::init(); | ||
10 | smol::run(async { | 12 | smol::run(async { |
11 | let addr = ([127, 0, 0, 1], 3000).into(); | 13 | let addr = ([127, 0, 0, 1], 3000).into(); |
12 | let service = | 14 | let service = |
13 | make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(shortner_service)) }); | 15 | make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(shortner_service)) }); |
14 | let server = Server::bind(&addr).serve(service); | 16 | let server = Server::bind(&addr).serve(service); |
15 | println!("Listening on http://{}", addr); | 17 | trace!("Listening on http://{}", addr); |
16 | server.await.unwrap(); | 18 | server.await.unwrap(); |
17 | Ok(()) | 19 | Ok(()) |
18 | }) | 20 | }) |
diff --git a/src/service.rs b/src/service.rs index 55a42bf..5883b40 100644 --- a/src/service.rs +++ b/src/service.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use anyhow::{Context, Result}; | 1 | use anyhow::{Context, Result}; |
2 | use hyper::header::CONTENT_TYPE; | 2 | use hyper::header::CONTENT_TYPE; |
3 | use hyper::{Body, Method, Request, Response, StatusCode}; | 3 | use hyper::{Body, Method, Request, Response, StatusCode}; |
4 | use log::{debug, error, info, trace}; | ||
4 | use multer::Multipart; | 5 | use multer::Multipart; |
5 | use nanoid::nanoid; | 6 | use nanoid::nanoid; |
6 | use rusqlite::{params, Connection}; | 7 | use rusqlite::{params, Connection}; |
@@ -11,6 +12,7 @@ use std::collections::HashMap; | |||
11 | use crate::db::init_db; | 12 | use crate::db::init_db; |
12 | 13 | ||
13 | fn respond_with_shortlink<S: AsRef<str>>(shortlink: S) -> Response<Body> { | 14 | fn respond_with_shortlink<S: AsRef<str>>(shortlink: S) -> Response<Body> { |
15 | info!("Successfully generated shortlink"); | ||
14 | Response::builder() | 16 | Response::builder() |
15 | .status(StatusCode::OK) | 17 | .status(StatusCode::OK) |
16 | .header("content-type", "text/html") | 18 | .header("content-type", "text/html") |
@@ -56,6 +58,7 @@ async fn process_multipart( | |||
56 | let mut m = Multipart::new(body, boundary); | 58 | let mut m = Multipart::new(body, boundary); |
57 | if let Some(field) = m.next_field().await? { | 59 | if let Some(field) = m.next_field().await? { |
58 | if field.name() == Some("shorten") { | 60 | if field.name() == Some("shorten") { |
61 | trace!("Recieved valid multipart request"); | ||
59 | let content = field | 62 | let content = field |
60 | .text() | 63 | .text() |
61 | .await | 64 | .await |
@@ -65,9 +68,8 @@ async fn process_multipart( | |||
65 | return Ok(respond_with_shortlink(shortlink)); | 68 | return Ok(respond_with_shortlink(shortlink)); |
66 | } | 69 | } |
67 | } | 70 | } |
68 | Ok(Response::builder() | 71 | trace!("Unprocessable multipart request!"); |
69 | .status(StatusCode::OK) | 72 | Ok(respond_with_status(StatusCode::UNPROCESSABLE_ENTITY)) |
70 | .body(Body::empty())?) | ||
71 | } | 73 | } |
72 | 74 | ||
73 | pub async fn shortner_service(req: Request<Body>) -> Result<Response<Body>> { | 75 | pub async fn shortner_service(req: Request<Body>) -> Result<Response<Body>> { |
@@ -91,19 +93,24 @@ pub async fn shortner_service(req: Request<Body>) -> Result<Response<Body>> { | |||
91 | .collect::<HashMap<String, String>>(); | 93 | .collect::<HashMap<String, String>>(); |
92 | 94 | ||
93 | if let Some(n) = params.get("shorten") { | 95 | if let Some(n) = params.get("shorten") { |
96 | trace!("POST: {}", &n); | ||
94 | let s = shorten(n, &mut conn)?; | 97 | let s = shorten(n, &mut conn)?; |
95 | return Ok(respond_with_shortlink(s)); | 98 | return Ok(respond_with_shortlink(s)); |
96 | } else { | 99 | } else { |
100 | error!("Invalid form"); | ||
97 | return Ok(respond_with_status(StatusCode::UNPROCESSABLE_ENTITY)); | 101 | return Ok(respond_with_status(StatusCode::UNPROCESSABLE_ENTITY)); |
98 | } | 102 | } |
99 | } | 103 | } |
100 | 104 | ||
105 | trace!("Attempting to parse multipart request"); | ||
101 | return process_multipart(req.into_body(), boundary.unwrap(), &mut conn).await; | 106 | return process_multipart(req.into_body(), boundary.unwrap(), &mut conn).await; |
102 | } | 107 | } |
103 | &Method::GET => { | 108 | &Method::GET => { |
109 | trace!("GET: {}", req.uri()); | ||
104 | let shortlink = req.uri().path().to_string(); | 110 | let shortlink = req.uri().path().to_string(); |
105 | let link = get_link(&shortlink[1..], &mut conn); | 111 | let link = get_link(&shortlink[1..], &mut conn); |
106 | if let Some(l) = link.unwrap() { | 112 | if let Some(l) = link.unwrap() { |
113 | trace!("Found in database, redirecting ..."); | ||
107 | Ok(Response::builder() | 114 | Ok(Response::builder() |
108 | .header("Location", &l) | 115 | .header("Location", &l) |
109 | .header("content-type", "text/html") | 116 | .header("content-type", "text/html") |
@@ -113,6 +120,7 @@ pub async fn shortner_service(req: Request<Body>) -> Result<Response<Body>> { | |||
113 | &l | 120 | &l |
114 | )))?) | 121 | )))?) |
115 | } else { | 122 | } else { |
123 | error!("Resource not found"); | ||
116 | Ok(respond_with_status(StatusCode::NOT_FOUND)) | 124 | Ok(respond_with_status(StatusCode::NOT_FOUND)) |
117 | } | 125 | } |
118 | } | 126 | } |