diff options
author | Ignacio Casal Quinteiro <qignacio@amazon.com> | 2021-02-03 15:41:40 +0100 |
---|---|---|
committer | Ignacio Casal Quinteiro <qignacio@amazon.com> | 2021-02-03 16:12:31 +0100 |
commit | 442d9d26e774bf9dc03e62781e6ddbc93e8ec1b6 (patch) | |
tree | 89b6eb515e940f3eafa142bd26205617b1396315 | |
parent | f33e3661ac9396cff357fd1f27dd2bb899ccb9e2 (diff) | |
download | libsoup-nacho/response-test.tar.gz |
Improve support for rfc 7230nacho/response-test
A server MUST NOT send a Content-Length header field in any response
with a status code of 1xx (Informational) or 204 (No Content)
-rw-r--r-- | libsoup/soup-message-server-io.c | 11 | ||||
-rw-r--r-- | tests/misc-test.c | 62 |
2 files changed, 72 insertions, 1 deletions
diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c index 71e943b6..e80e5511 100644 --- a/libsoup/soup-message-server-io.c +++ b/libsoup/soup-message-server-io.c @@ -266,7 +266,16 @@ get_response_headers (SoupMessage *msg, GString *headers, else *encoding = claimed_encoding; - if (claimed_encoding == SOUP_ENCODING_CONTENT_LENGTH && + + /* Per rfc 7230: + * A server MUST NOT send a Content-Length header field in any response + * with a status code of 1xx (Informational) or 204 (No Content). + */ + + if (msg->status_code == SOUP_STATUS_NO_CONTENT || + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) { + soup_message_headers_remove (msg->response_headers, "Content-Length"); + } else if (claimed_encoding == SOUP_ENCODING_CONTENT_LENGTH && !soup_message_headers_get_content_length (msg->response_headers)) { soup_message_headers_set_content_length (msg->response_headers, msg->response_body->length); diff --git a/tests/misc-test.c b/tests/misc-test.c index 8cbda80a..0f9b0d33 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -1188,6 +1188,66 @@ do_stealing_test (gconstpointer data) soup_test_server_quit_unref (server); } +static void +wrote_informational_check_content_length (SoupMessage *msg, gpointer user_data) +{ + g_assert_null (soup_message_headers_get_one (msg->response_headers, "Content-Length")); +} + +static void +upgrade_server_check_content_length_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS); + soup_message_headers_append (msg->request_headers, "Upgrade", "ECHO"); + soup_message_headers_append (msg->request_headers, "Connection", "upgrade"); + + g_signal_connect (msg, "wrote-informational", + G_CALLBACK (wrote_informational_check_content_length), context); +} + +static void +switching_protocols_check_length (SoupMessage *msg, gpointer user_data) +{ + g_assert_null (soup_message_headers_get_one (msg->response_headers, "Content-Length")); +} + +static void +do_response_informational_content_length_test (void) +{ + SoupServer *server; + SoupURI *uri; + SoupSession *session; + SoupMessage *msg; + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + uri = soup_test_server_get_uri (server, SOUP_URI_SCHEME_HTTP, NULL); + soup_server_add_handler (server, NULL, upgrade_server_check_content_length_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + msg = soup_message_new_from_uri ("GET", uri); + soup_message_headers_append (msg->request_headers, "Upgrade", "echo"); + soup_message_headers_append (msg->request_headers, "Connection", "upgrade"); + + soup_message_add_status_code_handler (msg, "got-informational", + SOUP_STATUS_SWITCHING_PROTOCOLS, + G_CALLBACK (switching_protocols_check_length), NULL); + + soup_session_send_message (session, msg); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + soup_uri_free (uri); + + soup_test_server_quit_unref (server); +} + int main (int argc, char **argv) { @@ -1232,6 +1292,8 @@ main (int argc, char **argv) g_test_add_func ("/misc/pause-cancel", do_pause_cancel_test); g_test_add_data_func ("/misc/stealing/async", GINT_TO_POINTER (FALSE), do_stealing_test); g_test_add_data_func ("/misc/stealing/sync", GINT_TO_POINTER (TRUE), do_stealing_test); + g_test_add_func ("/misc/response/informational/content-length", do_response_informational_content_length_test); + ret = g_test_run (); |