diff options
author | Dennis Eriksen <d@ennis.no> | 2023-07-02 20:08:13 +0200 |
---|---|---|
committer | Dennis Eriksen <d@ennis.no> | 2023-07-02 20:08:13 +0200 |
commit | bd7a078e6ccac195979c88107db9922195fd66e4 (patch) | |
tree | 3771b881e7ecbb9aaf3e80323cd972945e15b1bb | |
parent | trying to simplify create (diff) | |
download | purl-rs-bd7a078e6ccac195979c88107db9922195fd66e4.tar.gz |
moving stuff around
-rw-r--r-- | src/main.rs | 207 |
1 files changed, 105 insertions, 102 deletions
diff --git a/src/main.rs b/src/main.rs index 050a9ec..3af9e48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,103 +9,8 @@ use rand::{thread_rng, Rng, distributions::Alphanumeric}; -fn status<'a>(code:u16) -> &'a str { - // I've only implemented statuscodes I *might* use - return match code { - 200 => "OK", - 201 => "Created", - 202 => "Accepted", - 204 => "No Content", - 301 => "Moved Permanently", - 302 => "Found", - 304 => "Not Modified", - 307 => "Temporary Redirect", - 308 => "Permanent Redirect", - 400 => "Bad Request", - 401 => "Unauthorized", - 402 => "Payment Required", - 403 => "Forbidden", - 404 => "Not Found", - 405 => "Method Not Allowed", - 406 => "Not Acceptableo", - 410 => "Gone", - 414 => "URI Too Long", - 500 => "Internal Server Error", - 501 => "Not Implemented", - 503 => "Service Unavailable", - 508 => "Loop Detected", - _ => "Not Found", - }; -} - -// send cgi-response -fn respond(code:u16, body:&str) { - // initiate response - let mut r = EmptyResponse::new(code) - .with_content_type("text/plain"); - - // is 300 <= status < 400, and body is a url, perform redirection - if (300..399).contains(&code) && Url::parse(body).is_ok() { - r.add_header("Location", body); - } - - // if status >= 300, we want to include status text in the response - if code >= 300 { - write!(&mut r, "{} {}\n", code, status(code)).unwrap(); - if body != "" { - write!(&mut r, "\n").unwrap(); - } - } - - if body != "" { - // write body - write!(&mut r, "{}\n", body).unwrap(); - } - - // respond - r.respond().unwrap(); - exit(0); -} - - -// Print form -fn print_form() { - let body = r#"<html> -<head> - <title>PURL</title> -</head> -<body> - <form method="post" action="/purl.cgi" enctype="multipart/form-data" name="main"> - Username: $user<br> - URL to shorten: <input type="text" name="url" size="50"><br> - Custom short: <input type="text" name="short"><br> - <input type="hidden" name="form" value="html"> - <input type="submit" value="Submit"> - </form> -</body> -</html> -"#; - - respond(200, body); -} - - -// Generate random short -fn gen_short() -> String { - let rand_string: String = thread_rng() - .sample_iter(&Alphanumeric) - .take(thread_rng().gen_range(2..6)) - .map(char::from) - .collect(); - - return rand_string; -} - - // Do the dirty -// return std::io::Result<()> so we can use ? - -// https://doc.rust-lang.org/std/result/#the-question-mark-operator- -fn main() -> std::io::Result<()> { +fn main() { // short = ID for shortened url // url = url to be shortened / that has been shortened @@ -151,11 +56,12 @@ fn main() -> std::io::Result<()> { } // Fetch URL from postgres, and redirect or return 404 - - match db.query_opt("SELECT url FROM shorts WHERE short = $1 LIMIT 1", &[&docuri]).unwrap() { + let sql = "SELECT url FROM shorts WHERE short = $1 LIMIT 1"; + match db.query_opt(sql, &[&docuri]).unwrap() { None => respond(404, ""), Some(row) => { - db.execute("UPDATE shorts SET count = count + 1, last_visited = now() WHERE short = $1;", &[&docuri]).unwrap(); + let sql = "UPDATE shorts SET count = count + 1, last_visited = now() WHERE short = $1;"; + db.execute(sql, &[&docuri]).unwrap(); respond(301, row.get("url")); }, } @@ -184,7 +90,8 @@ fn main() -> std::io::Result<()> { let mut short:String = gen_short(); for i in 1..5 { - match db.query_opt("SELECT url FROM shorts WHERE short = $1 LIMIT 1", &[&short]).unwrap() { + let sql = "SELECT url FROM shorts WHERE short = $1 LIMIT 1"; + match db.query_opt(sql, &[&short]).unwrap() { Some(_row) => short = gen_short(), // If a row was returned, the short was not unique. Continue loop None => break, // If nothing was returned, the short IS unique. Break out of loop } @@ -193,7 +100,8 @@ fn main() -> std::io::Result<()> { if i == 5 { respond(500, "Could not find unique short"); } } - match db.execute("INSERT INTO shorts (url, short, created_by) VALUES ($1, $2, $3);", &[&url, &short, &user]) { + let sql = "INSERT INTO shorts (url, short, created_by) VALUES ($1, $2, $3);"; + match db.execute(sql, &[&url, &short, &user]) { Ok(_v) => respond(200, &format!("{}{}", shortprefix, short)), Err(_e) => respond(500, "Could not save shortened url to database"), }; @@ -204,7 +112,102 @@ fn main() -> std::io::Result<()> { else { respond(400, ""); } +} - Ok(()) + +// send cgi-response +fn respond(code:u16, body:&str) { + // initiate response + let mut r = EmptyResponse::new(code) + .with_content_type("text/plain"); + + // is 300 <= status < 400, and body is a url, perform redirection + if (300..399).contains(&code) && Url::parse(body).is_ok() { + r.add_header("Location", body); + } + + // if status >= 300, we want to include status text in the response + if code >= 300 { + let mut toptext = format!("{} {}\n", code, status(code)); + if !body.is_empty() { toptext.push_str("\n"); } + write!(&mut r, "{toptext}").unwrap(); + } + + if body != "" { + // write body + write!(&mut r, "{}\n", body).unwrap(); + } + + // respond + r.respond().unwrap(); + exit(0); +} + + + +// HTTP status codes +fn status<'a>(code:u16) -> &'a str { + // I've only implemented statuscodes I *might* use + return match code { + 200 => "OK", + 201 => "Created", + 202 => "Accepted", + 204 => "No Content", + 301 => "Moved Permanently", + 302 => "Found", + 304 => "Not Modified", + 307 => "Temporary Redirect", + 308 => "Permanent Redirect", + 400 => "Bad Request", + 401 => "Unauthorized", + 402 => "Payment Required", + 403 => "Forbidden", + 404 => "Not Found", + 405 => "Method Not Allowed", + 406 => "Not Acceptableo", + 410 => "Gone", + 414 => "URI Too Long", + 500 => "Internal Server Error", + 501 => "Not Implemented", + 503 => "Service Unavailable", + 508 => "Loop Detected", + _ => "Not Found", + }; +} + + + +// Print form +fn print_form() { + let body = r#"<html> +<head> + <title>PURL</title> +</head> +<body> + <form method="post" action="/purl.cgi" enctype="multipart/form-data" name="main"> + Username: $user<br> + URL to shorten: <input type="text" name="url" size="50"><br> + Custom short: <input type="text" name="short"><br> + <input type="hidden" name="form" value="html"> + <input type="submit" value="Submit"> + </form> +</body> +</html> +"#; + + respond(200, body); +} + + + +// Generate random short +fn gen_short() -> String { + let rand_string: String = thread_rng() + .sample_iter(&Alphanumeric) + .take(thread_rng().gen_range(2..6)) + .map(char::from) + .collect(); + + return rand_string; } |