aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDennis Eriksen <d@ennis.no>2023-07-01 21:28:42 +0200
committerDennis Eriksen <d@ennis.no>2023-07-01 21:28:42 +0200
commit7350cf84c3bf0df1bd34c8f4dae40ac5795c17bb (patch)
treedd7c6eaea3d2452fc0f87dedf251f985f4f36e8c /src
parentCleaning up. Starting with response-function. (diff)
downloadpurl-rs-7350cf84c3bf0df1bd34c8f4dae40ac5795c17bb.tar.gz
More cleaning up. TODO: More cleaning up
Diffstat (limited to 'src')
-rw-r--r--src/main.rs167
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, "");
}