[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.