gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] 02/02: Added MHD_RF_HEAD_ONLY_RESPONSE response flag


From: gnunet
Subject: [libmicrohttpd] 02/02: Added MHD_RF_HEAD_ONLY_RESPONSE response flag
Date: Thu, 17 Mar 2022 18:52:05 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit 41f35bbcb5d2771ea37ed920c34d8092a58dc432
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Thu Mar 17 20:50:32 2022 +0300

    Added MHD_RF_HEAD_ONLY_RESPONSE response flag
    
    Useful if application needs to send reply for HEAD request, but creation
    of full reply body is costly.
---
 src/include/microhttpd.h    | 28 +++++++++++++++++++----
 src/microhttpd/connection.c | 36 +++++++++++++++++++++++++++--
 src/microhttpd/response.c   | 55 ++++++++++++++++++++++++++++++---------------
 3 files changed, 95 insertions(+), 24 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index e49afdad..fd9ddaba 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -1,7 +1,7 @@
 /*
      This file is part of libmicrohttpd
      Copyright (C) 2006-2021 Christian Grothoff (and other contributing 
authors)
-     Copyright (C) 2014-2021 Evgeny Grin (Karlson2k)
+     Copyright (C) 2014-2022 Evgeny Grin (Karlson2k)
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -96,7 +96,7 @@ extern "C"
  * they are parsed as decimal numbers.
  * Example: 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00097501
+#define MHD_VERSION 0x00097502
 
 /* If generic headers don't work on your platform, include headers
    which define 'va_list', 'size_t', 'ssize_t', 'intptr_t',
@@ -3234,7 +3234,10 @@ MHD_lookup_connection_value_n (struct MHD_Connection 
*connection,
  * header is added automatically based the size of the body in the response.
  * If body size it set to #MHD_SIZE_UNKNOWN or chunked encoding is enforced
  * then "Transfer-Encoding: chunked" header (for HTTP/1.1 only) is added 
instead
- * of "Content-Length" header.
+ * of "Content-Length" header. For example, if response with zero-size body is
+ * used for HEAD request, then "Content-Length: 0" is added automatically to
+ * reply headers.
+ * @sa #MHD_RF_HEAD_ONLY_RESPONSE
  *
  * In situations, where reply body is required, like answer for the GET request
  * with @a status_code #MHD_HTTP_OK, headers "Content-Length" (for known body
@@ -3364,6 +3367,8 @@ enum MHD_ResponseFlags
   /**
    * Disable sanity check preventing clients from manually
    * setting the HTTP content length option.
+   * Allow to set several "Content-Length" headers. These headers will
+   * be used even with replies without body.
    * @note Available since #MHD_VERSION 0x00096702
    */
   MHD_RF_INSANITY_HEADER_CONTENT_LENGTH = 1 << 2,
@@ -3374,7 +3379,22 @@ enum MHD_ResponseFlags
    * Disabled by default for HTTP/1.1 clients as per RFC.
    * @note Available since #MHD_VERSION 0x00097310
    */
-  MHD_RF_SEND_KEEP_ALIVE_HEADER = 1 << 3
+  MHD_RF_SEND_KEEP_ALIVE_HEADER = 1 << 3,
+
+  /**
+   * Enable special processing of the response as body-less (with undefined
+   * body size). No automatic "Content-Length" or "Transfer-Encoding: chunked"
+   * headers are added when the response is used with #MHD_HTTP_NOT_MODIFIED
+   * code or to respond to HEAD request.
+   * The flag also allow to set arbitrary "Content-Length" by
+   * MHD_add_response_header() function.
+   * This flag value can be used only with responses created without body
+   * (zero-size body).
+   * Responses with this flag enabled cannot be used in situations where
+   * reply body must be sent to the client.
+   * @note Available since #MHD_VERSION 0x00097502
+   */
+  MHD_RF_HEAD_ONLY_RESPONSE = 1 << 4
 } _MHD_FIXED_FLAGS_ENUM;
 
 
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index f4b09f43..9e59738c 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1913,6 +1913,7 @@ buffer_append (char *buf,
  * @param buf_size the size of the @a buf
  * @param response the response
  * @param filter_transf_enc skip "Transfer-Encoding" header if any
+ * @param filter_content_len skip "Content-Length" header if any
  * @param add_close add "close" token to the
  *                  "Connection:" header (if any), ignored if no "Connection:"
  *                  header was added by user or if "close" token is already
@@ -1928,6 +1929,7 @@ add_user_headers (char *buf,
                   size_t buf_size,
                   struct MHD_Response *response,
                   bool filter_transf_enc,
+                  bool filter_content_len,
                   bool add_close,
                   bool add_keep_alive)
 {
@@ -1938,7 +1940,9 @@ add_user_headers (char *buf,
   mhd_assert (! add_close || ! add_keep_alive);
 
   if (0 == (r->flags_auto & MHD_RAF_HAS_TRANS_ENC_CHUNKED))
-    filter_transf_enc = false;  /* No such header */
+    filter_transf_enc = false;   /* No such header */
+  if (0 == (r->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH))
+    filter_content_len = false;  /* No such header */
   if (0 == (r->flags_auto & MHD_RAF_HAS_CONNECTION_HDR))
   {
     add_close = false;          /* No such header */
@@ -1963,6 +1967,19 @@ add_user_headers (char *buf,
         continue; /* Skip "Transfer-Encoding" header */
       }
     }
+    if (filter_content_len)
+    { /* Need to filter-out "Content-Length" */
+      if ((MHD_STATICSTR_LEN_ (MHD_HTTP_HEADER_CONTENT_LENGTH) ==
+           hdr->header_size) &&
+          (MHD_str_equal_caseless_bin_n_ (MHD_HTTP_HEADER_CONTENT_LENGTH,
+                                          hdr->header, hdr->header_size)) )
+      {
+        /* Reset filter flag if only one header is allowed */
+        filter_transf_enc =
+          (0 == (r->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH));
+        continue; /* Skip "Content-Length" header */
+      }
+    }
 
     /* Add user header */
     el_size = hdr->header_size + 2 + hdr->value_size + 2;
@@ -2184,13 +2201,17 @@ build_header_response (struct MHD_Connection 
*connection)
 
   if (! add_user_headers (buf, &pos, buf_size, r,
                           ! c->rp_props.chunked,
+                          (! c->rp_props.use_reply_body_headers) &&
+                          (0 ==
+                           (r->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)),
                           use_conn_close,
                           use_conn_k_alive))
     return MHD_NO;
 
   /* Other automatic headers */
 
-  if (c->rp_props.use_reply_body_headers)
+  if ( (c->rp_props.use_reply_body_headers) &&
+       (0 == (r->flags & MHD_RF_HEAD_ONLY_RESPONSE)) )
   {
     /* Body-specific headers */
 
@@ -5320,6 +5341,17 @@ MHD_queue_response (struct MHD_Connection *connection,
     return MHD_NO;
   }
 
+  if ( (0 != (MHD_RF_HEAD_ONLY_RESPONSE & response->flags)) &&
+       (RP_BODY_HEADERS_ONLY < is_reply_body_needed (connection, status_code)) 
)
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (daemon,
+              _ ("HEAD-only response cannot be used when the request requires "
+                 "reply body to be sent!\n"));
+#endif
+    return MHD_NO;
+  }
+
 #ifdef HAVE_MESSAGES
   if ( (0 != (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) &&
        (0 != (MHD_RAF_HAS_CONTENT_LENGTH & response->flags_auto)) )
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 7468a232..3803da2b 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -501,9 +501,12 @@ MHD_add_response_header (struct MHD_Response *response,
                                MHD_HTTP_HEADER_TRANSFER_ENCODING))
   {
     if (! MHD_str_equal_caseless_ (content, "chunked"))
-      return MHD_NO;
+      return MHD_NO;   /* Only "chunked" encoding is allowed */
     if (0 != (response->flags_auto & MHD_RAF_HAS_TRANS_ENC_CHUNKED))
-      return MHD_YES;
+      return MHD_YES;  /* Already has "chunked" encoding header */
+    if ( (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH)) &&
+         (0 == (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) )
+      return MHD_NO; /* Has "Content-Length" header and no "Insanity" flag */
     if (MHD_NO != add_response_entry (response,
                                       MHD_HEADER_KIND,
                                       header,
@@ -545,19 +548,22 @@ MHD_add_response_header (struct MHD_Response *response,
   if (MHD_str_equal_caseless_ (header,
                                MHD_HTTP_HEADER_CONTENT_LENGTH))
   {
-    if (0 == (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags))
-    {
-      /* MHD sets automatically correct Content-Length always when needed,
-         reject attempt to manually override it */
-      return MHD_NO;
-    }
-    if (MHD_NO != add_response_entry (response,
-                                      MHD_HEADER_KIND,
-                                      header,
-                                      content))
+    /* Generally MHD sets automatically correct "Content-Length" always when
+     * needed.
+     * Custom "Content-Length" header is allowed only in special cases. */
+    if ( (0 != (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) ||
+         ((0 != (MHD_RF_HEAD_ONLY_RESPONSE & response->flags)) &&
+          (0 == (response->flags_auto & (MHD_RAF_HAS_TRANS_ENC_CHUNKED
+                                         | MHD_RAF_HAS_CONTENT_LENGTH)))) )
     {
-      response->flags_auto |= MHD_RAF_HAS_CONTENT_LENGTH;
-      return MHD_YES;
+      if (MHD_NO != add_response_entry (response,
+                                        MHD_HEADER_KIND,
+                                        header,
+                                        content))
+      {
+        response->flags_auto |= MHD_RAF_HAS_CONTENT_LENGTH;
+        return MHD_YES;
+      }
     }
     return MHD_NO;
   }
@@ -895,12 +901,25 @@ MHD_set_response_options (struct MHD_Response *response,
   enum MHD_Result ret;
   enum MHD_ResponseOptions ro;
 
-  if ( (0 != (response->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)) &&
-       (0 == (flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)))
-  { /* Request to remove MHD_RF_INSANITY_HEADER_CONTENT_LENGTH flag */
-    if (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH))
+  if (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH))
+  { /* Response has custom "Content-Lengh" header */
+    if ( (0 != (response->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)) &&
+         (0 == (flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)))
+    { /* Request to remove MHD_RF_INSANITY_HEADER_CONTENT_LENGTH flag */
       return MHD_NO;
+    }
+    if ( (0 != (response->flags & MHD_RF_HEAD_ONLY_RESPONSE)) &&
+         (0 == (flags & MHD_RF_HEAD_ONLY_RESPONSE)))
+    { /* Request to remove MHD_RF_HEAD_ONLY_RESPONSE flag */
+      if (0 == (flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH))
+        return MHD_NO;
+    }
   }
+
+  if ( (0 != (flags & MHD_RF_HEAD_ONLY_RESPONSE)) &&
+       (0 != response->total_size) )
+    return MHD_NO;
+
   ret = MHD_YES;
   response->flags = flags;
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]