[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 07/07: response: process "Connection" header in a specia
From: |
gnunet |
Subject: |
[libmicrohttpd] 07/07: response: process "Connection" header in a special manner |
Date: |
Mon, 05 Jul 2021 16:07:48 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit e1693575ed0edfd2c0f09abcfd1df3021c1f793e
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Mon Jul 5 12:57:34 2021 +0300
response: process "Connection" header in a special manner
---
src/microhttpd/.gitignore | 1 +
src/microhttpd/Makefile.am | 8 +-
src/microhttpd/internal.h | 17 +
src/microhttpd/response.c | 230 ++++++++++++
src/microhttpd/test_response_entries.c | 618 +++++++++++++++++++++++++++++++++
5 files changed, 873 insertions(+), 1 deletion(-)
diff --git a/src/microhttpd/.gitignore b/src/microhttpd/.gitignore
index 0ff01aac..3b0d8ce4 100644
--- a/src/microhttpd/.gitignore
+++ b/src/microhttpd/.gitignore
@@ -55,6 +55,7 @@ test_http_reasons
/test_str_token
/test_str_token_remove
/test_str_tokens_remove
+/test_response_entries
test_shutdown_poll
test_shutdown_select
test_md5
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 369e5554..e610c1df 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -166,6 +166,7 @@ check_PROGRAMS = \
test_sha256 \
test_start_stop \
test_daemon \
+ test_response_entries \
test_postprocessor_md \
test_options
@@ -217,13 +218,18 @@ endif
test_start_stop_SOURCES = \
test_start_stop.c
test_start_stop_LDADD = \
- $(top_builddir)/src/microhttpd/libmicrohttpd.la
+ libmicrohttpd.la
test_daemon_SOURCES = \
test_daemon.c
test_daemon_LDADD = \
$(top_builddir)/src/microhttpd/libmicrohttpd.la
+test_response_entries_SOURCES = \
+ test_response_entries.c
+test_response_entries_LDADD = \
+ libmicrohttpd.la
+
test_upgrade_SOURCES = \
test_upgrade.c test_helpers.h mhd_sockets.h
test_upgrade_CPPFLAGS = \
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 5b5e9396..d1f3b9ff 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -351,6 +351,18 @@ struct MHD_HTTP_Header
};
+/**
+ * Automatically assigned flags
+ */
+enum MHD_ResponseAutoFlags
+{
+ MHD_RAF_NO_FLAGS = 0, /**< No auto flags */
+ MHD_RAF_HAS_CONNECTION_HDR = 1 << 0, /**< Has "Connection" header */
+ MHD_RAF_HAS_CONNECTION_CLOSE = 1 << 1, /**< Has "Connection: close" */
+ MHD_RAF_HAS_TRANS_ENC_CHUNKED = 2 << 2 /**< Has "Transfer-Encoding: chunked
*/
+} _MHD_FIXED_FLAGS_ENUM;
+
+
#if defined(MHD_WINSOCK_SOCKETS)
/**
* Internally used I/O vector type for use with winsock.
@@ -510,6 +522,11 @@ struct MHD_Response
*/
enum MHD_ResponseFlags flags;
+ /**
+ * Automatic flags set for the MHD response.
+ */
+ enum MHD_ResponseAutoFlags flags_auto;
+
/**
* If the @e fd is a pipe (no sendfile()).
*/
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 5d22640a..674cef0d 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -193,6 +193,227 @@ add_response_entry (struct MHD_Response *response,
}
+/**
+ * Add "Connection:" header to the response with special processing.
+ *
+ * "Connection:" header value will be combined with any existing "Connection:"
+ * header, "close" token (if any) will be de-duplicated and moved to the first
+ * position.
+ *
+ * @param response the response to add a header to
+ * @param value the value to add
+ * @return #MHD_NO on error (no memory).
+ */
+static enum MHD_Result
+add_response_header_connection (struct MHD_Response *response,
+ const char *value)
+{
+ static const char *key = "Connection";
+ /** the length of the "Connection" key */
+ static const size_t key_len = MHD_STATICSTR_LEN_ ("Connection");
+ size_t value_len; /**< the length of the @a value */
+ size_t old_value_len; /**< the length of the existing "Connection" value */
+ size_t buf_size; /**< the size of the buffer */
+ ssize_t norm_len; /**< the length of the normalised value */
+ char *buf; /**< the temporal buffer */
+ struct MHD_HTTP_Header *hdr; /**< existing "Connection" header */
+ bool value_has_close; /**< the @a value has "close" token */
+ bool already_has_close; /**< existing "Connection" header has "close" token
*/
+ size_t pos = 0; /**< position of addition in the @a buf */
+
+ if ( (NULL != strchr (value, '\r')) ||
+ (NULL != strchr (value, '\n')) )
+ return MHD_NO;
+
+ if (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR))
+ {
+ hdr = MHD_get_response_element_n_ (response, MHD_HEADER_KIND,
+ key, key_len);
+ already_has_close =
+ (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
+ mhd_assert (already_has_close == (0 == memcmp (hdr->value, "close", 5)));
+ mhd_assert (NULL != hdr);
+ }
+ else
+ {
+ hdr = NULL;
+ already_has_close = false;
+ mhd_assert (NULL == MHD_get_response_element_n_ (response,
+ MHD_HEADER_KIND,
+ key, key_len));
+ mhd_assert (0 == (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
+ }
+ if (NULL != hdr)
+ old_value_len = hdr->value_size + 2; /* additional size for ", " */
+ else
+ old_value_len = 0;
+
+ value_len = strlen (value);
+ /* Additional space for normalisation and zero-termination*/
+ norm_len = (ssize_t) (value_len + value_len / 2 + 1);
+ buf_size = old_value_len + (size_t) norm_len;
+
+ buf = malloc (buf_size);
+ if (NULL == buf)
+ return MHD_NO;
+ /* Move "close" token (if any) to the front */
+ value_has_close = MHD_str_remove_token_caseless_ (value, value_len, "close",
+ MHD_STATICSTR_LEN_ ( \
+ "close"),
+ buf + old_value_len,
+ &norm_len);
+ mhd_assert (0 <= norm_len);
+ if (0 > norm_len)
+ norm_len = 0; /* Must never happen */
+ if (0 == norm_len)
+ { /* New value is empty after normalisation */
+ if (! value_has_close)
+ { /* The new value had no tokens */
+ free (buf);
+ return MHD_NO;
+ }
+ if (already_has_close)
+ { /* The "close" token is already present, nothing to modify */
+ free (buf);
+ return MHD_YES;
+ }
+ }
+ /* Add "close" token if required */
+ if (value_has_close && ! already_has_close)
+ {
+ /* Need to insert "close" token at the first position */
+ mhd_assert (buf_size >= old_value_len + (size_t) norm_len \
+ + MHD_STATICSTR_LEN_ ("close, ") + 1);
+ if (0 != norm_len)
+ memmove (buf + MHD_STATICSTR_LEN_ ("close, ") + old_value_len,
+ buf + old_value_len, norm_len + 1);
+ memcpy (buf, "close", MHD_STATICSTR_LEN_ ("close"));
+ pos += MHD_STATICSTR_LEN_ ("close");
+ }
+ /* Add old value tokens (if any) */
+ if (0 != old_value_len)
+ {
+ if (0 != pos)
+ {
+ buf[pos++] = ',';
+ buf[pos++] = ' ';
+ }
+ memcpy (buf + pos, hdr->value,
+ hdr->value_size);
+ pos += hdr->value_size;
+ }
+ /* Add new value token (if any) */
+ if (0 != norm_len)
+ {
+ if (0 != pos)
+ {
+ buf[pos++] = ',';
+ buf[pos++] = ' ';
+ }
+ /* The new value tokens must be already at the correct position */
+ mhd_assert ((value_has_close && ! already_has_close) ? \
+ (MHD_STATICSTR_LEN_ ("close, ") + old_value_len == pos) : \
+ (old_value_len == pos));
+ pos += (size_t) norm_len;
+ }
+ mhd_assert (buf_size > pos);
+ buf[pos] = 0; /* Null terminate the result */
+
+ if (NULL == hdr)
+ {
+ struct MHD_HTTP_Header *new_hdr; /**< new "Connection" header */
+ /* Create new response header entry */
+ new_hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Header));
+ if (NULL != new_hdr)
+ {
+ new_hdr->header = malloc (key_len + 1);
+ if (NULL != new_hdr->header)
+ {
+ memcpy (new_hdr->header, key, key_len + 1);
+ new_hdr->header_size = key_len;
+ new_hdr->value = buf;
+ new_hdr->value_size = pos;
+ new_hdr->kind = MHD_HEADER_KIND;
+ if (value_has_close)
+ response->flags_auto = (MHD_RAF_HAS_CONNECTION_HDR
+ | MHD_RAF_HAS_CONNECTION_CLOSE);
+ else
+ response->flags_auto = MHD_RAF_HAS_CONNECTION_HDR;
+ _MHD_insert_header_first (response, new_hdr);
+ return MHD_YES;
+ }
+ free (new_hdr);
+ }
+ free (buf);
+ return MHD_NO;
+ }
+
+ /* Update existing header entry */
+ free (hdr->value);
+ hdr->value = buf;
+ hdr->value_size = pos;
+ if (value_has_close && ! already_has_close)
+ response->flags_auto |= MHD_RAF_HAS_CONNECTION_CLOSE;
+ return MHD_YES;
+}
+
+
+/**
+ * Remove tokens from "Connection:" header of the response.
+ *
+ * Provided tokens will be removed from "Connection:" header value.
+ *
+ * @param response the response to manipulate "Connection:" header
+ * @param value the tokens to remove
+ * @return #MHD_NO on error (no headers or tokens found).
+ */
+static enum MHD_Result
+del_response_header_connection (struct MHD_Response *response,
+ const char *value)
+{
+ struct MHD_HTTP_Header *hdr; /**< existing "Connection" header */
+
+ hdr = MHD_get_response_element_n_ (response, MHD_HEADER_KIND, "Connection",
+ MHD_STATICSTR_LEN_ ("Connection"));
+ if (NULL == hdr)
+ return MHD_NO;
+
+ if (! MHD_str_remove_tokens_caseless_ (hdr->value, &hdr->value_size, value,
+ strlen (value)))
+ return MHD_NO;
+ if (0 == hdr->value_size)
+ {
+ _MHD_remove_header (response, hdr);
+ free (hdr->value);
+ free (hdr->header);
+ free (hdr);
+ response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_HDR
+ | MHD_RAF_HAS_CONNECTION_CLOSE);
+ }
+ else
+ {
+ hdr->value[hdr->value_size] = 0; /* Null-terminate the result */
+ if (0 != (response->flags_auto & ~(MHD_RAF_HAS_CONNECTION_CLOSE)))
+ {
+ if (MHD_STATICSTR_LEN_ ("close") == hdr->value_size)
+ {
+ if (0 != memcmp (hdr->value, "close", MHD_STATICSTR_LEN_ ("close")))
+ response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+ }
+ else if (MHD_STATICSTR_LEN_ ("close, ") < hdr->value_size)
+ {
+ if (0 != memcmp (hdr->value, "close, ",
+ MHD_STATICSTR_LEN_ ("close, ")))
+ response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+ }
+ else
+ response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+ }
+ }
+ return MHD_YES;
+}
+
+
/**
* Add a header line to the response.
*
@@ -232,6 +453,9 @@ MHD_add_response_header (struct MHD_Response *response,
const char *header,
const char *content)
{
+ if (MHD_str_equal_caseless_ (header, MHD_HTTP_HEADER_CONNECTION))
+ return add_response_header_connection (response, content);
+
if (MHD_str_equal_caseless_ (header,
MHD_HTTP_HEADER_TRANSFER_ENCODING))
{
@@ -308,6 +532,12 @@ MHD_del_response_header (struct MHD_Response *response,
(NULL == content) )
return MHD_NO;
header_len = strlen (header);
+
+ if ((0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR)) &&
+ (MHD_STATICSTR_LEN_ ("Connection") == header_len) &&
+ MHD_str_equal_caseless_bin_n_ (header, "Connection", header_len))
+ return del_response_header_connection (response, content);
+
content_len = strlen (content);
pos = response->first_header;
while (NULL != pos)
diff --git a/src/microhttpd/test_response_entries.c
b/src/microhttpd/test_response_entries.c
new file mode 100644
index 00000000..5a21b025
--- /dev/null
+++ b/src/microhttpd/test_response_entries.c
@@ -0,0 +1,618 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2021 Karlson2k (Evgeny Grin)
+
+ This test_response_entries.c file is in the public domain
+*/
+
+/**
+ * @file test_response_entries.c
+ * @brief Test adding and removing response headers
+ * @author Karlson2k (Evgeny Grin)
+ */
+#include "mhd_options.h"
+#include "platform.h"
+#include <string.h>
+#include <microhttpd.h>
+
+
+static int
+expect_str (const char *actual, const char *expected)
+{
+ if (expected == actual)
+ return ! 0;
+ if (NULL == actual)
+ {
+ fprintf (stderr, "FAILED: result: NULL\n" \
+ " expected: \"%s\"",
+ expected);
+ return 0;
+ }
+ if (NULL == expected)
+ {
+ fprintf (stderr, "FAILED: result: \"%s\"\n" \
+ " expected: NULL",
+ actual);
+ return 0;
+ }
+ if (0 != strcmp (actual, expected))
+ {
+ fprintf (stderr, "FAILED: result: \"%s\"\n" \
+ " expected: \"%s\"",
+ actual, expected);
+ return 0;
+ }
+ return ! 0;
+}
+
+
+int
+main (int argc,
+ char *const *argv)
+{
+ (void) argc;
+ (void) argv; /* Unused. Silence compiler warning. */
+ struct MHD_Response *r;
+
+ r = MHD_create_response_from_buffer (0, "", MHD_RESPMEM_PERSISTENT);
+ if (NULL == r)
+ {
+ fprintf (stderr, "Cannot create a response.\n");
+ return 1;
+ }
+
+ /* ** Test basic header functions ** */
+
+ /* Add first header */
+ if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a1"))
+ {
+ fprintf (stderr, "Cannot add header A1.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a1"))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Add second header with the same name */
+ if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a2"))
+ {
+ fprintf (stderr, "Cannot add header A2.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Value of the first header must be returned */
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a1"))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Remove the first header */
+ if (MHD_YES != MHD_del_response_header (r, "Header-Type-A", "value-a1"))
+ {
+ fprintf (stderr, "Cannot remove header A1.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Value of the ex-second header must be returned */
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a3"))
+ {
+ fprintf (stderr, "Cannot add header A2.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Value of the ex-second header must be returned */
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ /* Remove the last header */
+ if (MHD_YES != MHD_del_response_header (r, "Header-Type-A", "value-a3"))
+ {
+ fprintf (stderr, "Cannot add header A2.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Header-Type-B"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (MHD_NO != MHD_del_response_header (r, "Header-Type-C", "value-a3"))
+ {
+ fprintf (stderr, "Removed non-existing header.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+ if (MHD_NO != MHD_del_response_header (r, "Header-Type-A", "value-c"))
+ {
+ fprintf (stderr, "Removed non-existing header value.\n");
+ MHD_destroy_response (r);
+ return 2;
+ }
+
+ /* ** Test "Connection:" header ** */
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "a,b,c,d,e"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with simple values.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "a, b, c, d,
e"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "e,b,c,d,a"))
+ {
+ fprintf (stderr,
+ "Cannot remove \"Connection\" header with simple values.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection",
+ "i,k,l,m,n,o,p,close"))
+ {
+ fprintf (stderr,
+ "Cannot add \"Connection\" header with simple values and
\"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, i, k, l, m, n, o, p"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "i,k,l,m,n,o,p,close"))
+ {
+ fprintf (stderr,
+ "Cannot remove \"Connection\" header with simple values and
\"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection",
+ "1,2,3,4,5,6,7,close"))
+ {
+ fprintf (stderr,
+ "Cannot add \"Connection\" header with simple values and
\"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, 1, 2, 3, 4, 5, 6, 7"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "8,9,close"))
+ {
+ fprintf (stderr,
+ "Cannot add second \"Connection\" header with simple values and
\"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, 1, 2, 3, 4, 5, 6, 7, 8, 9"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "1,3,5,7,9"))
+ {
+ fprintf (stderr,
+ "Cannot remove part of \"Connection\" header with simple
values.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, 2, 4, 6, 8"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "10,12"))
+ {
+ fprintf (stderr,
+ "Cannot add third \"Connection\" header with simple values.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, 2, 4, 6, 8, 10, 12"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "12 ,10 ,8 ,close"))
+ {
+ fprintf (stderr,
+ "Cannot remove part of \"Connection\" header with simple values
and \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "2, 4, 6"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\"
only.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, 2, 4, 6"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "4 ,5,6,7 8,"))
+ {
+ fprintf (stderr,
+ "Cannot remove part of \"Connection\" header with simple values
and non-existing tokens.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "close, 2"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\"
only.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "close, 2"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "close, 10, 12, 22, nothing"))
+ {
+ fprintf (stderr,
+ "Cannot remove part of \"Connection\" header with \"close\" and
non-existing tokens.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "2"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "2"))
+ {
+ fprintf (stderr,
+ "Cannot remove part of \"Connection\" header with simple values
and non-existing tokens.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot remove \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection",
"close,other-token"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, other-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close, new-token"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, other-token, new-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "close, new-token"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "other-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "other-token"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection",
+ "close, one-long-token"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, one-long-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, one-long-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "one-long-token,close"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection",
+ "close, additional-token"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, additional-token"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "additional-token,close"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "token-1,token-2"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "token-1, token-2"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "token-3"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "token-1, token-2, token-3"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, token-1, token-2, token-3"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, token-1, token-2, token-3"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close, token-4"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, token-1, token-2, token-3, token-4"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection", "close"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "token-1, token-2, token-3, token-4"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_add_response_header (r, "Connection", "close, token-5"))
+ {
+ fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, token-1, token-2, token-3, token-4, token-5"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_NO != MHD_del_response_header (r, "Connection",
+ "non-existing, token-9"))
+ {
+ fprintf (stderr,
+ "Non-existing tokens successfully removed from \"Connection\"
header.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"),
+ "close, token-1, token-2, token-3, token-4, token-5"))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_NO != MHD_add_response_header (r, "Connection",
+ ",,,,,,,,,,,, ,\t\t\t, , , "))
+ {
+ fprintf (stderr,
+ "Empty token was added successfully to \"Connection\" header.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_YES != MHD_del_response_header (r, "Connection",
+ "close, token-1, token-2, token-3,
token-4, token-5"))
+ {
+ fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (MHD_NO != MHD_add_response_header (r, "Connection",
+ ",,,,,,,,,,,, ,\t\t\t, , , "))
+ {
+ fprintf (stderr,
+ "Empty token was added successfully to \"Connection\" header.\n");
+ MHD_destroy_response (r);
+ return 3;
+ }
+ if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+ {
+ MHD_destroy_response (r);
+ return 3;
+ }
+
+ MHD_destroy_response (r);
+ printf ("All tests has been successfully passed.\n");
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] branch master updated (64e91ef6 -> e1693575), gnunet, 2021/07/05
- [libmicrohttpd] 03/07: Corrected internal doxy, gnunet, 2021/07/05
- [libmicrohttpd] 04/07: MHD_del_response_header(): removed unused variable, gnunet, 2021/07/05
- [libmicrohttpd] 02/07: mhd_str: minor optimisation, gnunet, 2021/07/05
- [libmicrohttpd] 01/07: mhd_str: minor code refactoring, gnunet, 2021/07/05
- [libmicrohttpd] 06/07: Added MHD_str_remove_tokens_caseless_() function, gnunet, 2021/07/05
- [libmicrohttpd] 05/07: Added MHD_str_remove_token_caseless_() function, gnunet, 2021/07/05
- [libmicrohttpd] 07/07: response: process "Connection" header in a special manner,
gnunet <=