From ec334ef78b6cc7b0fc0ae6817d41d8b40fdd5695 Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Sun, 30 May 2021 17:33:41 +0200
Subject: [PATCH] feat(gva): use sub-path for playground and subscriptions

Consequently:
- deletion of the GVASUB endpoint
- remove conf param playground_path
- remove conf param subscriptions_path
---
 conf/src/lib.rs |  45 ---------------------
 src/lib.rs      |  63 ++++++-----------------------
 src/warp_.rs    | 104 +++++++++++++++++++++++++++++-------------------
 3 files changed, 74 insertions(+), 138 deletions(-)

diff --git a/conf/src/lib.rs b/conf/src/lib.rs
index 126b017..fd690ef 100644
--- a/conf/src/lib.rs
+++ b/conf/src/lib.rs
@@ -34,14 +34,9 @@ pub struct GvaConf {
     pub port: u16,
     #[serde(default = "path_default")]
     pub path: String,
-    #[serde(default = "playground_path_default")]
-    pub playground_path: String,
-    #[serde(default = "subscriptions_path_default")]
-    pub subscriptions_path: String,
     pub remote_host: Option<String>,
     pub remote_port: Option<u16>,
     pub remote_path: Option<String>,
-    pub remote_subscriptions_path: Option<String>,
     pub remote_tls: Option<bool>,
     #[serde(default = "whitelist_default")]
     pub whitelist: Vec<IpAddr>,
@@ -59,18 +54,10 @@ fn path_default() -> String {
     "gva".to_owned()
 }
 
-fn playground_path_default() -> String {
-    "gva-playground".to_owned()
-}
-
 const fn port_default() -> u16 {
     30_901
 }
 
-fn subscriptions_path_default() -> String {
-    "gva-sub".to_owned()
-}
-
 fn whitelist_default() -> Vec<IpAddr> {
     vec![
         IpAddr::V4(Ipv4Addr::LOCALHOST),
@@ -85,13 +72,10 @@ impl Default for GvaConf {
             ip4: ip4_default(),
             ip6: Some(ip6_default()),
             port: port_default(),
-            playground_path: playground_path_default(),
             path: path_default(),
-            subscriptions_path: subscriptions_path_default(),
             remote_host: None,
             remote_port: None,
             remote_path: None,
-            remote_subscriptions_path: None,
             remote_tls: None,
             whitelist: whitelist_default(),
         }
@@ -107,11 +91,6 @@ impl GvaConf {
             .clone()
             .unwrap_or_else(|| self.path.clone())
     }
-    pub fn get_remote_subscriptions_path(&self) -> String {
-        self.remote_subscriptions_path
-            .clone()
-            .unwrap_or_else(|| self.subscriptions_path.clone())
-    }
 }
 
 #[derive(StructOpt)]
@@ -171,19 +150,6 @@ impl GvaCommand {
                 .msg(format!("Path ? [{}]", conf.path))
                 .default(conf.path)
                 .get();
-            // playgroundPath
-            conf.path = input()
-                .msg(format!("playground path ? [{}]", conf.playground_path))
-                .default(conf.playground_path.clone())
-                .get();
-            // subscriptionsPath
-            conf.subscriptions_path = input()
-                .msg(format!(
-                    "Subscriptions path ? [{}]",
-                    conf.subscriptions_path
-                ))
-                .default(conf.subscriptions_path)
-                .get();
             // remoteHost
             if let Some(ref remote_host) = conf.remote_host {
                 let new_remote_host = input()
@@ -225,17 +191,6 @@ impl GvaCommand {
             } else {
                 conf.remote_path = None;
             }
-            // remoteSubscriptionsPath
-            let res = input()
-                .msg("Define a remote subscriptions path? [y/N]")
-                .default('N')
-                .get();
-            if res == 'y' || res == 'Y' {
-                conf.remote_subscriptions_path =
-                    Some(input().msg("Enter remote subscriptions path:").get());
-            } else {
-                conf.remote_subscriptions_path = None;
-            }
             // whitelist
             let mut whitelist: HashSet<_> = conf.whitelist.iter().copied().collect();
             let res = input().msg("Update whitelist? [y/N]").default('N').get();
diff --git a/src/lib.rs b/src/lib.rs
index bad7d1e..ed68001 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -51,6 +51,9 @@ use std::{convert::Infallible, path::Path};
 use tests::get_public_ips;
 use warp::{http::Response as HttpResponse, Filter as _, Rejection};
 
+const PLAYGROUND_SUB_PATH: &str = "playground";
+const SUBSCRIPTION_SUB_PATH: &str = "subscription";
+
 #[derive(Debug)]
 pub struct GvaModule {
     conf: GvaConf,
@@ -270,29 +273,16 @@ impl GvaModule {
         );
 
         // Create warp server routes
-        let graphql_post = warp_::graphql(
+        let gva_route = warp_::gva_route(
             &conf,
             gva_schema.clone(),
             async_graphql::http::MultipartOptions::default(),
         );
-
-        let conf_clone = conf.clone();
-        let graphql_playground = warp::path::path(conf.playground_path.clone())
-            .and(warp::get())
-            .map(move || {
-                HttpResponse::builder()
-                    .header("content-type", "text/html")
-                    .body(async_graphql::http::playground_source(
-                        GraphQLPlaygroundConfig::new(&format!("/{}", &conf_clone.path))
-                            .subscription_endpoint(
-                                &format!("/{}", &conf_clone.subscriptions_path,),
-                            ),
-                    ))
-            });
-
-        let routes = graphql_playground
-            .or(graphql_post)
-            .or(warp_::graphql_ws(&conf, gva_schema.clone()))
+        let gva_playground_route = warp_::gva_playground_route(&conf);
+        let gva_subscription_route = warp_::gva_subscription_route(&conf, gva_schema.clone());
+        let routes = gva_route
+            .or(gva_subscription_route)
+            .or(gva_playground_route)
             .recover(|err: Rejection| async move {
                 if let Some(warp_::BadRequest(err)) = err.find() {
                     return Ok::<_, Infallible>(warp::reply::with_status(
@@ -373,17 +363,6 @@ impl GvaModule {
                 remote_port,
                 conf.get_remote_path(),
             ));
-            endpoints.push(format!(
-                "GVASUB {}{} {} {}",
-                if remote_port == 443 || conf.remote_tls.unwrap_or_default() {
-                    "S "
-                } else {
-                    ""
-                },
-                remote_hosh,
-                remote_port,
-                conf.get_remote_subscriptions_path(),
-            ));
         }
         Ok(endpoints)
     }
@@ -433,13 +412,7 @@ mod tests {
             },
         )
         .await?;
-        assert_eq!(
-            endpoints,
-            vec![
-                "GVA 0.0.0.0 [::] 30901 gva".to_owned(),
-                "GVASUB 0.0.0.0 [::] 30901 gva-sub".to_owned()
-            ]
-        );
+        assert_eq!(endpoints, vec!["GVA 0.0.0.0 [::] 30901 gva".to_owned(),]);
 
         // only ip4 find
         let endpoints = test_gen_endpoints(
@@ -450,13 +423,7 @@ mod tests {
             },
         )
         .await?;
-        assert_eq!(
-            endpoints,
-            vec![
-                "GVA 0.0.0.0 30901 gva".to_owned(),
-                "GVASUB 0.0.0.0 30901 gva-sub".to_owned()
-            ]
-        );
+        assert_eq!(endpoints, vec!["GVA 0.0.0.0 30901 gva".to_owned(),]);
 
         // only ip6 find
         let endpoints = test_gen_endpoints(
@@ -467,13 +434,7 @@ mod tests {
             },
         )
         .await?;
-        assert_eq!(
-            endpoints,
-            vec![
-                "GVA [::] 30901 gva".to_owned(),
-                "GVASUB [::] 30901 gva-sub".to_owned()
-            ]
-        );
+        assert_eq!(endpoints, vec!["GVA [::] 30901 gva".to_owned(),]);
 
         // No ips find
         assert!(test_gen_endpoints(
diff --git a/src/warp_.rs b/src/warp_.rs
index bcde9d5..e602eee 100644
--- a/src/warp_.rs
+++ b/src/warp_.rs
@@ -142,7 +142,25 @@ fn add_cache_control(http_resp: &mut warp::reply::Response, resp: &async_graphql
     }
 }
 
-pub(crate) fn graphql(
+pub(crate) fn gva_playground_route(
+    conf: &GvaConf,
+) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone {
+    let gva_path = conf.path.clone();
+    warp::path::path(gva_path.clone())
+        .and(warp::path::path(PLAYGROUND_SUB_PATH))
+        .and(warp::get())
+        .map(move || {
+            HttpResponse::builder()
+                .header("content-type", "text/html")
+                .body(async_graphql::http::playground_source(
+                    GraphQLPlaygroundConfig::new(&format!("/{}", &gva_path)).subscription_endpoint(
+                        &format!("/{}/{}", &gva_path, SUBSCRIPTION_SUB_PATH),
+                    ),
+                ))
+        })
+}
+
+pub(crate) fn gva_route(
     conf: &GvaConf,
     gva_schema: GvaSchema,
     opts: async_graphql::http::MultipartOptions,
@@ -150,6 +168,7 @@ pub(crate) fn graphql(
     let anti_spam = AntiSpam::from(conf);
     let opts = Arc::new(opts);
     warp::path::path(conf.path.clone())
+        .and(warp::path::end())
         .and(warp::method())
         .and(warp::query::raw().or(warp::any().map(String::new)).unify())
         .and(warp::addr::remote())
@@ -223,51 +242,13 @@ pub(crate) fn graphql(
         )
 }
 
-async fn process_bincode_batch_queries(
-    body_reader: impl 'static + futures::TryStream<Ok = Bytes, Error = std::io::Error> + Send + Unpin,
-    is_whitelisted: bool,
-) -> Result<ServerResponse, warp::Rejection> {
-    Ok(ServerResponse::Bincode(
-        duniter_bda::execute(body_reader, is_whitelisted).await,
-    ))
-}
-
-async fn process_json_batch_queries(
-    body_reader: impl 'static + futures::AsyncRead + Send + Unpin,
-    content_type: Option<String>,
-    gva_schema: GvaSchema,
-    is_whitelisted: bool,
-    opts: async_graphql::http::MultipartOptions,
-) -> Result<ServerResponse, warp::Rejection> {
-    let batch_request = GraphQlRequest::new(
-        async_graphql::http::receive_batch_body(
-            content_type,
-            body_reader,
-            async_graphql::http::MultipartOptions::clone(&opts),
-        )
-        .await
-        .map_err(|err| warp::reject::custom(BadRequest(err.into())))?,
-    );
-    if is_whitelisted || batch_request.len() <= anti_spam::MAX_BATCH_SIZE {
-        Ok(ServerResponse::GraphQl(
-            batch_request
-                .data(QueryContext { is_whitelisted })
-                .execute(gva_schema)
-                .await,
-        ))
-    } else {
-        Err(warp::reject::custom(BadRequest(anyhow::Error::msg(
-            r#"{ "error": "The batch contains too many requests" }"#,
-        ))))
-    }
-}
-
-pub(crate) fn graphql_ws(
+pub(crate) fn gva_subscription_route(
     conf: &GvaConf,
     schema: GvaSchema,
 ) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone {
     let anti_spam = AntiSpam::from(conf);
-    warp::path::path(conf.subscriptions_path.clone())
+    warp::path::path(conf.path.clone())
+        .and(warp::path::path(SUBSCRIPTION_SUB_PATH))
         .and(warp::addr::remote())
         .and(warp::header::optional::<IpAddr>("X-Real-IP"))
         .and(warp::ws())
@@ -326,3 +307,42 @@ pub(crate) fn graphql_ws(
             )))
         })
 }
+
+async fn process_bincode_batch_queries(
+    body_reader: impl 'static + futures::TryStream<Ok = Bytes, Error = std::io::Error> + Send + Unpin,
+    is_whitelisted: bool,
+) -> Result<ServerResponse, warp::Rejection> {
+    Ok(ServerResponse::Bincode(
+        duniter_bda::execute(body_reader, is_whitelisted).await,
+    ))
+}
+
+async fn process_json_batch_queries(
+    body_reader: impl 'static + futures::AsyncRead + Send + Unpin,
+    content_type: Option<String>,
+    gva_schema: GvaSchema,
+    is_whitelisted: bool,
+    opts: async_graphql::http::MultipartOptions,
+) -> Result<ServerResponse, warp::Rejection> {
+    let batch_request = GraphQlRequest::new(
+        async_graphql::http::receive_batch_body(
+            content_type,
+            body_reader,
+            async_graphql::http::MultipartOptions::clone(&opts),
+        )
+        .await
+        .map_err(|err| warp::reject::custom(BadRequest(err.into())))?,
+    );
+    if is_whitelisted || batch_request.len() <= anti_spam::MAX_BATCH_SIZE {
+        Ok(ServerResponse::GraphQl(
+            batch_request
+                .data(QueryContext { is_whitelisted })
+                .execute(gva_schema)
+                .await,
+        ))
+    } else {
+        Err(warp::reject::custom(BadRequest(anyhow::Error::msg(
+            r#"{ "error": "The batch contains too many requests" }"#,
+        ))))
+    }
+}
-- 
GitLab