[vlc-commits] http: add manager flag for non-idempotent requests

Rémi Denis-Courmont git at videolan.org
Sun Oct 4 16:19:23 CEST 2020


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Oct  4 16:56:32 2020 +0300| [075d089cc3873aeece38f2e5d8cbb9dbdf674807] | committer: Rémi Denis-Courmont

http: add manager flag for non-idempotent requests

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=075d089cc3873aeece38f2e5d8cbb9dbdf674807
---

 modules/access/http/connmgr.c   | 53 +++++++++++++++++++++++++----------------
 modules/access/http/connmgr.h   |  4 +++-
 modules/access/http/file_test.c |  4 +++-
 modules/access/http/resource.c  |  2 +-
 4 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/modules/access/http/connmgr.c b/modules/access/http/connmgr.c
index 5105fdc3fe..7f16405536 100644
--- a/modules/access/http/connmgr.c
+++ b/modules/access/http/connmgr.c
@@ -136,11 +136,6 @@ struct vlc_http_msg *vlc_http_mgr_reuse(struct vlc_http_mgr *mgr,
         struct vlc_http_msg *m = vlc_http_msg_get_initial(stream);
         if (m != NULL)
             return m;
-
-        /* NOTE: If the request were not idempotent, we would not know if it
-         * was processed by the other end. Thus POST is not used/supported so
-         * far, and CONNECT is treated as if it were idempotent (which works
-         * fine here). */
     }
     /* Get rid of closing or reset connection */
     vlc_http_mgr_release(mgr, conn);
@@ -149,7 +144,8 @@ struct vlc_http_msg *vlc_http_mgr_reuse(struct vlc_http_mgr *mgr,
 
 static struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
                                               const char *host, unsigned port,
-                                              const struct vlc_http_msg *req)
+                                              const struct vlc_http_msg *req,
+                                              bool idempotent)
 {
     vlc_tls_t *tls;
     bool http2 = true;
@@ -164,10 +160,16 @@ static struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
             return NULL;
     }
 
-    /* TODO? non-idempotent request support */
-    struct vlc_http_msg *resp = vlc_http_mgr_reuse(mgr, host, port, req);
-    if (resp != NULL)
-        return resp; /* existing connection reused */
+    if (idempotent)
+    {   /* If the request is idempotent, try to reuse an existing connection.
+         * Otherwise, it is possible but unadvisable as we would not know if
+         * the nonidempotent request was processed if the connection fails
+         * before the response is received.
+         */
+        struct vlc_http_msg *resp = vlc_http_mgr_reuse(mgr, host, port, req);
+        if (resp != NULL)
+            return resp; /* existing connection reused */
+    }
 
     char *proxy = vlc_http_proxy_find(host, port, true);
     if (proxy != NULL)
@@ -202,21 +204,27 @@ static struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
         return NULL;
     }
 
-    mgr->conn = conn;
+    if (mgr->conn != NULL)
+        vlc_http_mgr_release(mgr, mgr->conn);
 
+    mgr->conn = conn;
     return vlc_http_mgr_reuse(mgr, host, port, req);
 }
 
 static struct vlc_http_msg *vlc_http_request(struct vlc_http_mgr *mgr,
                                              const char *host, unsigned port,
-                                             const struct vlc_http_msg *req)
+                                             const struct vlc_http_msg *req,
+                                             bool idempotent)
 {
     if (mgr->creds != NULL && mgr->conn != NULL)
         return NULL; /* switch from HTTPS to HTTP not implemented */
 
-    struct vlc_http_msg *resp = vlc_http_mgr_reuse(mgr, host, port, req);
-    if (resp != NULL)
-        return resp;
+    if (idempotent)
+    {
+        struct vlc_http_msg *resp = vlc_http_mgr_reuse(mgr, host, port, req);
+        if (resp != NULL)
+            return resp;
+    }
 
     struct vlc_http_conn *conn;
     struct vlc_http_stream *stream;
@@ -232,7 +240,7 @@ static struct vlc_http_msg *vlc_http_request(struct vlc_http_mgr *mgr,
         if (url.psz_host != NULL)
             stream = vlc_h1_request(mgr->logger, url.psz_host,
                                     url.i_port ? url.i_port : 80, true, req,
-                                    true, false, &conn);
+                                    idempotent, false, &conn);
         else
             stream = NULL;
 
@@ -240,30 +248,35 @@ static struct vlc_http_msg *vlc_http_request(struct vlc_http_mgr *mgr,
     }
     else
         stream = vlc_h1_request(mgr->logger, host, port ? port : 80, false,
-                                req, true, false, &conn);
+                                req, idempotent, false, &conn);
 
     if (stream == NULL)
         return NULL;
 
-    resp = vlc_http_msg_get_initial(stream);
+    struct vlc_http_msg *resp = vlc_http_msg_get_initial(stream);
     if (resp == NULL)
     {
         vlc_http_conn_release(conn);
         return NULL;
     }
 
+    if (mgr->conn != NULL)
+        vlc_http_mgr_release(mgr, mgr->conn);
+
     mgr->conn = conn;
     return resp;
 }
 
 struct vlc_http_msg *vlc_http_mgr_request(struct vlc_http_mgr *mgr, bool https,
                                           const char *host, unsigned port,
-                                          const struct vlc_http_msg *m)
+                                          const struct vlc_http_msg *m,
+                                          bool idempotent)
 {
     if (port && vlc_http_port_blocked(port))
         return NULL;
 
-    return (https ? vlc_https_request : vlc_http_request)(mgr, host, port, m);
+    return (https ? vlc_https_request : vlc_http_request)(mgr, host, port, m,
+                                                          idempotent);
 }
 
 struct vlc_http_cookie_jar_t *vlc_http_mgr_get_jar(struct vlc_http_mgr *mgr)
diff --git a/modules/access/http/connmgr.h b/modules/access/http/connmgr.h
index a4c258842d..e853e1fde6 100644
--- a/modules/access/http/connmgr.h
+++ b/modules/access/http/connmgr.h
@@ -45,12 +45,14 @@ struct vlc_http_cookie_jar_t;
  * @param host name of authoritative HTTP server to send the request to
  * @param port TCP server port number, or 0 for the default port number
  * @param req HTTP request header to send
+ * @param idempotent whether the request is idempotent
  *
  * @return The initial HTTP response header, or NULL in case of failure.
  */
 struct vlc_http_msg *vlc_http_mgr_request(struct vlc_http_mgr *mgr, bool https,
                                           const char *host, unsigned port,
-                                          const struct vlc_http_msg *req);
+                                          const struct vlc_http_msg *req,
+                                          bool idempotent);
 
 struct vlc_http_cookie_jar_t *vlc_http_mgr_get_jar(struct vlc_http_mgr *);
 
diff --git a/modules/access/http/file_test.c b/modules/access/http/file_test.c
index 5779812056..fbe55d4689 100644
--- a/modules/access/http/file_test.c
+++ b/modules/access/http/file_test.c
@@ -336,7 +336,8 @@ static struct vlc_http_stream stream = { &stream_callbacks };
 
 struct vlc_http_msg *vlc_http_mgr_request(struct vlc_http_mgr *mgr, bool https,
                                           const char *host, unsigned port,
-                                          const struct vlc_http_msg *req)
+                                          const struct vlc_http_msg *req,
+                                          bool idempotent)
 {
     const char *str;
     char *end;
@@ -345,6 +346,7 @@ struct vlc_http_msg *vlc_http_mgr_request(struct vlc_http_mgr *mgr, bool https,
     assert(mgr == NULL);
     assert(!strcmp(host, "www.example.com"));
     assert(port == 8443);
+    assert(idempotent);
 
     str = vlc_http_msg_get_method(req);
     assert(!strcmp(str, "GET"));
diff --git a/modules/access/http/resource.c b/modules/access/http/resource.c
index 5f5406a11c..2550146d00 100644
--- a/modules/access/http/resource.c
+++ b/modules/access/http/resource.c
@@ -91,7 +91,7 @@ retry:
         return NULL;
 
     struct vlc_http_msg *resp = vlc_http_mgr_request(res->manager, res->secure,
-                                                    res->host, res->port, req);
+                                              res->host, res->port, req, true);
     vlc_http_msg_destroy(req);
 
     resp = vlc_http_msg_get_final(resp);



More information about the vlc-commits mailing list