changeset 94:ddbdd16ebd7e

geohub: Refactor HTTP return methods
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 08 Dec 2020 22:03:51 +0100
parents c683521147c7
children ebc250ea457f
files src/http.rs src/main.rs
diffstat 2 files changed, 64 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/http.rs	Tue Dec 08 22:03:32 2020 +0100
+++ b/src/http.rs	Tue Dec 08 22:03:51 2020 +0100
@@ -3,52 +3,92 @@
 use std::io::Read;
 
 #[derive(Responder)]
+pub struct GeoHubResponder {
+    inner: GeoHubResponse,
+    cd: rocket::http::hyper::header::ContentDisposition,
+}
+
+#[derive(Responder)]
 pub enum GeoHubResponse {
     #[response(status = 200, content_type = "plain")]
     Ok(String),
     #[response(status = 200, content_type = "json")]
     Json(String),
-    #[response(status = 200, content_type = "application/xml")]
-    Xml(String),
+    #[response(status = 200, content_type = "application/gpx+xml")]
+    Gpx(String),
     #[response(status = 400)]
     BadRequest(String),
     #[response(status = 500)]
     ServerError(String),
 }
 
-pub fn return_xml(xml: String) -> GeoHubResponse {
-    GeoHubResponse::Xml(xml)
+fn content_disposition(attachment: bool) -> rocket::http::hyper::header::ContentDisposition {
+    rocket::http::hyper::header::ContentDisposition {
+            disposition: if attachment { rocket::http::hyper::header::DispositionType::Attachment } else { rocket::http::hyper::header::DispositionType::Inline },
+            parameters: vec![],
+        }
+}
+
+pub fn return_ok(s: String) -> GeoHubResponder {
+    let resp = GeoHubResponder {
+        inner: GeoHubResponse::Ok(s),
+        cd: content_disposition(false),
+    };
+    resp
 }
 
-pub fn return_json<T: serde::Serialize>(obj: &T) -> GeoHubResponse {
+pub fn return_gpx(gx: String) -> GeoHubResponder {
+    let resp = GeoHubResponder {
+        inner: GeoHubResponse::Gpx(gx),
+        cd: content_disposition(true),
+    };
+    resp
+}
+
+pub fn return_json<T: serde::Serialize>(obj: &T) -> GeoHubResponder {
     let json = serde_json::to_string(&obj);
+    let cd = content_disposition(true);
     if let Ok(json) = json {
-        return GeoHubResponse::Json(json);
+        let resp = GeoHubResponder {
+            inner: GeoHubResponse::Json(json),
+            cd: cd,
+        };
+        return resp;
     } else {
-        return GeoHubResponse::ServerError(json.unwrap_err().to_string());
+        let resp = GeoHubResponder {
+            inner: GeoHubResponse::ServerError(json.unwrap_err().to_string()),
+            cd: cd,
+        };
+        return resp;
     }
 }
 
-pub fn bad_request(msg: String) -> GeoHubResponse {
-    GeoHubResponse::BadRequest(msg)
+pub fn bad_request(msg: String) -> GeoHubResponder {
+    GeoHubResponder {
+        inner: GeoHubResponse::BadRequest(msg),
+        cd: content_disposition(false),
+    }
 }
 
 use std::fmt::Debug;
 
-pub fn server_error<E: Debug>(err: E) -> GeoHubResponse {
-    GeoHubResponse::ServerError(format!("{:?}", err))
+pub fn server_error<E: Debug>(err: E) -> GeoHubResponder {
+    GeoHubResponder {
+        inner: GeoHubResponse::ServerError(format!("{:?}", err)),
+        cd: content_disposition(false),
+    }
 }
 
-pub fn read_data(d: rocket::Data, limit: u64) -> Result<String, GeoHubResponse> {
+pub fn read_data(d: rocket::Data, limit: u64) -> Result<String, GeoHubResponder> {
     let mut ds = d.open().take(limit);
     let mut dest = Vec::with_capacity(limit as usize);
     if let Err(e) = std::io::copy(&mut ds, &mut dest) {
-        return Err(GeoHubResponse::BadRequest(format!(
+        return Err(bad_request(format!(
             "Error reading request: {}",
             e
         )));
     }
 
     String::from_utf8(dest)
-        .map_err(|e| GeoHubResponse::BadRequest(format!("Decoding error: {}", e)))
+        .map_err(|e| bad_request(format!("Decoding error: {}", e)))
 }
--- a/src/main.rs	Tue Dec 08 22:03:32 2020 +0100
+++ b/src/main.rs	Tue Dec 08 22:03:51 2020 +0100
@@ -60,7 +60,7 @@
     name: String,
     secret: Option<String>,
     timeout: Option<u64>,
-) -> http::GeoHubResponse {
+) -> http::GeoHubResponder {
     if !ids::name_and_secret_acceptable(name.as_str(), secret.as_ref().map(|s| s.as_str())) {
         return http::bad_request(
             "You have supplied an invalid secret or name. Both must be ASCII alphanumeric strings."
@@ -90,7 +90,7 @@
     to: Option<String>,
     limit: Option<i64>,
     last: Option<i32>,
-) -> http::GeoHubResponse {
+) -> http::GeoHubResponder {
     let result = common_retrieve(db, client, secret, from, to, limit, last);
     match result {
         Ok(points) => {
@@ -111,7 +111,7 @@
     to: Option<String>,
     limit: Option<i64>,
     last: Option<i32>,
-) -> http::GeoHubResponse {
+) -> http::GeoHubResponder {
     let result = common_retrieve(db, client, secret, from, to, limit, last);
     match result {
         Ok(points) => {
@@ -121,7 +121,7 @@
                 return he;
             }
             match String::from_utf8(serialized) {
-                Ok(xml) => http::return_xml(xml),
+                Ok(gx) => http::return_gpx(gx),
                 Err(e) => http::server_error(e),
             }
         }
@@ -137,7 +137,7 @@
     to: Option<String>,
     limit: Option<i64>,
     last: Option<i32>,
-) -> Result<Vec<types::GeoPoint>, http::GeoHubResponse> {
+) -> Result<Vec<types::GeoPoint>, http::GeoHubResponder> {
     if !ids::name_and_secret_acceptable(client.as_str(), secret.as_ref().map(|s| s.as_str())) {
         return Err(http::bad_request(
             "You have supplied an invalid secret or client. Both must be ASCII alphanumeric strings."
@@ -193,7 +193,7 @@
     ele: Option<f64>,
     accuracy: Option<f64>,
     note: rocket::data::Data,
-) -> http::GeoHubResponse {
+) -> http::GeoHubResponder {
     // Check that secret and client name are legal.
     if !ids::name_and_secret_acceptable(name.as_str(), secret.as_ref().map(|s| s.as_str())) {
         return http::bad_request(
@@ -245,7 +245,7 @@
     if let Err(e) = notify_manager.send_notification(&db, name.as_str(), &secret, Some(1)) {
         eprintln!("Couldn't send notification: {}", e);
     }
-    http::GeoHubResponse::Ok("".into())
+    http::return_ok("".into())
 }
 
 /// Ingest GeoJSON.
@@ -256,7 +256,7 @@
     name: String,
     secret: Option<String>,
     body: rocket_contrib::json::Json<types::LogLocations>,
-) -> http::GeoHubResponse {
+) -> http::GeoHubResponder {
     // Check that secret and client name are legal.
     if !ids::name_and_secret_acceptable(name.as_str(), secret.as_ref().map(|s| s.as_str())) {
         return http::bad_request(
@@ -293,7 +293,7 @@
     }
 
     if errs.is_empty() {
-        http::GeoHubResponse::Ok("".into())
+        http::return_ok("".into())
     } else {
         let errstring = errs
             .into_iter()
@@ -302,7 +302,7 @@
             .collect::<Vec<String>>()
             .join(";");
         eprintln!("Couldn't write points: {}", errstring);
-        http::GeoHubResponse::Ok(errstring)
+        http::server_error(errstring)
     }
 }