aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.rs207
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;
}