diff options
author | Dennis Eriksen <d@ennis.no> | 2023-07-01 21:28:42 +0200 |
---|---|---|
committer | Dennis Eriksen <d@ennis.no> | 2023-07-01 21:28:42 +0200 |
commit | 7350cf84c3bf0df1bd34c8f4dae40ac5795c17bb (patch) | |
tree | dd7c6eaea3d2452fc0f87dedf251f985f4f36e8c /src | |
parent | Cleaning up. Starting with response-function. (diff) | |
download | purl-rs-7350cf84c3bf0df1bd34c8f4dae40ac5795c17bb.tar.gz |
More cleaning up. TODO: More cleaning up
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 167 |
1 files changed, 86 insertions, 81 deletions
diff --git a/src/main.rs b/src/main.rs index 28e5cd7..da58431 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,15 @@ use std::process::exit; use regex::Regex; use dotenv; use url::Url; -use rand::{thread_rng, Rng}; -use rand::distributions::Alphanumeric; +use rand::{thread_rng, Rng, distributions::Alphanumeric}; + // Get URL from database -fn get_url(dburl:&str, short:&str, update:bool) -> Result<String, postgres::Error> { +fn get_url(short:&str, update:bool) -> Result<String, postgres::Error> { // Connect to db + let dburl:String = dotenv::var("DATABASE_URL").unwrap(); let mut client = Client::connect(&dburl, NoTls)?; let row = client.query_one("SELECT url FROM shorts WHERE short = $1 LIMIT 1", &[&short])?; @@ -27,7 +28,8 @@ fn get_url(dburl:&str, short:&str, update:bool) -> Result<String, postgres::Erro Ok(url) } -fn insert_short(dburl:String, url: &str, short: &str, user: &str) -> Result<u64, postgres::Error> { +fn insert_short(url: &str, short: &str, user: &str) -> Result<u64, postgres::Error> { + let dburl:String = dotenv::var("DATABASE_URL").unwrap(); let mut client = Client::connect(&dburl, NoTls)?; let n = client.execute("INSERT INTO shorts (url, short, created_by) VALUES ($1, $2, $3);", &[&url, &short, &user])?; @@ -64,21 +66,31 @@ fn status<'a>(code:u16) -> &'a str { }; } -// Do the redirect +// send cgi-response fn respond(code:u16, body:&str) { + // initiate response let mut r = EmptyResponse::new(code) .with_content_type("text/plain"); - if code >= 300 { - write!(&mut r, "{} {}\n\n", code, status(code)).unwrap(); - } - + // 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); } - write!(&mut r, "{}\n", body).unwrap(); + // 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); } @@ -86,7 +98,7 @@ fn respond(code:u16, body:&str) { // Print form fn print_form() { - let html = r#"<html> + let body = r#"<html> <head> <title>PURL</title> </head> @@ -98,17 +110,11 @@ fn print_form() { <input type="hidden" name="form" value="html"> <input type="submit" value="Submit"> </form> - </body> </html> -HTML "#; - EmptyResponse::new(200) - .with_content_type("text/html") - .with_body(html) - .respond().unwrap(); - exit(0); + respond(200, body); } @@ -137,8 +143,6 @@ fn main() -> std::io::Result<()> { // Example: "/hey" in "https://example.com/hey" - // Get dburl from .env-file - let dburl = dotenv::var("DATABASE_URL").unwrap(); let shortprefix = dotenv::var("SHORTPREFIX").unwrap(); // Gather all request data from the environment and stdin. @@ -147,72 +151,73 @@ fn main() -> std::io::Result<()> { // Find out what action we're performing let action:&str = req.var("ACTION").unwrap_or("none"); - match action { - "form" => print_form(), - - "redirect" => { - // get DOCUMENT_URI - let docuri:&str = req.var("DOCUMENT_URI").unwrap_or("none"); - // Trim / and + from start - let docuri = docuri.trim_start_matches(&['/', '+']); - - // Make SURE docuri is a valid short - let shortregex = Regex::new(r"^[a-zA-Z0-9_-]+$").unwrap(); - if !shortregex.is_match(docuri) { - respond(400, "Bad Request"); - } - - // Fetch URL from postgres, and redirect or return 404 - match get_url(&dburl, docuri, true) { - Ok(url) => respond(301, &url), - Err(_e) => respond(404, "Not Found"), - }; - }, - - "create" => { - match req.query() { - Query::None => respond(303, "/purl.cgi"), - Query::Some(map) => { - if map.iter().count() != 1 { - respond(400, "Bad Request\n\nIncorrect number of query items"); - } - let url:&str = &map["url"]; - if !Url::parse(url).is_ok() { - respond(400, "Bad Request\n\nInvalid url"); + if action == "form" { + print_form(); + } + + else if action == "redirect" { + // get DOCUMENT_URI + let docuri:&str = req.var("DOCUMENT_URI").unwrap_or(""); + if docuri == "" { + respond(400, "No short provided"); + } + + // Trim / and + from start + let docuri = docuri.trim_start_matches(&['/', '+']); + + // Make SURE docuri is a valid short + let shortregex = Regex::new(r"^[a-zA-Z0-9_-]+$").unwrap(); + if !shortregex.is_match(docuri) { + respond(400, "Not a valid short"); + } + + // Fetch URL from postgres, and redirect or return 404 + match get_url(docuri, true) { + Ok(url) => respond(301, &url), + Err(_e) => respond(404, ""), + }; + } + + else if action == "create" { + match req.query() { + Query::None => respond(303, "/purl.cgi"), + Query::Some(map) => { + if map.iter().count() != 1 { + respond(400, "Incorrect number of query items"); + } + let url:&str = &map["url"]; + if !Url::parse(url).is_ok() { + respond(400, "Invalid url"); + } + + let user:&str = req.var("REMOTE_USER").unwrap_or("none"); + let mut short:String = gen_short(); + + for i in 1..5 { + match get_url(&short, false) { + Ok(_url) => short = gen_short(), // If Ok, then short is already in + // use. Try a new one. + Err(_e) => break, // we assume that we found a unique short if get_url + // returns an error } - let user:&str = req.var("REMOTE_USER").unwrap_or("none"); - let mut short:String = gen_short(); + // Throw error if we couldn't create a unique short in fire tries + if i == 5 { respond(500, "Could not find unique short"); } + } - for i in 1..5 { - match get_url(&dburl, &short, false) { - Ok(_url) => short = gen_short(), // If Ok, then short is already in - // use. Try a new one. - Err(_e) => break, // we assume that we found a unique short if get_url - // returns an error - } + match insert_short(url, &short, user) { + Ok(_v) => respond(200, &format!("{}{}", shortprefix, short)), + Err(_e) => respond(400, "looool"), + }; + exit(0); - // Throw error if we couldn't create a unique short in fire tries - if i == 5 { respond(500, "Could not find unique short"); } - } + }, + Query::Err(_e) => respond(400,"Error reading query string"), + } + } - match insert_short(dburl, url, &short, user) { - Ok(_v) => respond(200, &format!("{}{}", shortprefix, short)), - Err(_e) => respond(400, "looool"), - }; - //if n == 1 { - // respond(200, &res); - //} else { - // respond(400, "Bad Request\n\nDunno wtf happened"); - //} - exit(0); - - }, - Query::Err(_e) => respond(400,"Bad Request\n\nError reading query string"), - } - }, - - _ => respond(400, "Bad Request"), + else { + respond(400, ""); } |