1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-message.c: HTTP request/response
5 * Copyright (C) 2000-2003, Ximian, Inc.
11 #include "soup-auth.h"
12 #include "soup-marshal.h"
13 #include "soup-message.h"
14 #include "soup-message-private.h"
15 #include "soup-misc.h"
16 #include "soup-server-message.h"
19 G_DEFINE_TYPE (SoupMessage, soup_message, G_TYPE_OBJECT)
38 static guint signals[LAST_SIGNAL] = { 0 };
40 static void wrote_body (SoupMessage *req);
41 static void got_headers (SoupMessage *req);
42 static void got_chunk (SoupMessage *req);
43 static void got_body (SoupMessage *req);
44 static void restarted (SoupMessage *req);
45 static void finished (SoupMessage *req);
46 static void free_chunks (SoupMessage *msg);
49 soup_message_init (SoupMessage *msg)
51 msg->status = SOUP_MESSAGE_STATUS_IDLE;
53 msg->request_headers = g_hash_table_new (soup_str_case_hash,
56 msg->response_headers = g_hash_table_new (soup_str_case_hash,
59 SOUP_MESSAGE_GET_PRIVATE (msg)->http_version = SOUP_HTTP_1_1;
63 finalize (GObject *object)
65 SoupMessage *msg = SOUP_MESSAGE (object);
66 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
68 soup_message_io_stop (msg);
71 soup_uri_free (priv->uri);
73 if (msg->request.owner == SOUP_BUFFER_SYSTEM_OWNED)
74 g_free (msg->request.body);
75 if (msg->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
76 g_free (msg->response.body);
79 soup_message_clear_headers (msg->request_headers);
80 g_hash_table_destroy (msg->request_headers);
82 soup_message_clear_headers (msg->response_headers);
83 g_hash_table_destroy (msg->response_headers);
85 g_slist_foreach (priv->content_handlers, (GFunc) g_free, NULL);
86 g_slist_free (priv->content_handlers);
88 g_free ((char *) msg->reason_phrase);
90 G_OBJECT_CLASS (soup_message_parent_class)->finalize (object);
94 soup_message_class_init (SoupMessageClass *message_class)
96 GObjectClass *object_class = G_OBJECT_CLASS (message_class);
98 g_type_class_add_private (message_class, sizeof (SoupMessagePrivate));
100 /* virtual method definition */
101 message_class->wrote_body = wrote_body;
102 message_class->got_headers = got_headers;
103 message_class->got_chunk = got_chunk;
104 message_class->got_body = got_body;
105 message_class->restarted = restarted;
106 message_class->finished = finished;
108 /* virtual method override */
109 object_class->finalize = finalize;
114 * SoupMessage::wrote-informational:
117 * Emitted immediately after writing a 1xx (Informational)
118 * response for a message.
120 signals[WROTE_INFORMATIONAL] =
121 g_signal_new ("wrote_informational",
122 G_OBJECT_CLASS_TYPE (object_class),
124 G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
126 soup_marshal_NONE__NONE,
130 * SoupMessage::wrote-headers:
133 * Emitted immediately after writing the headers for a message.
135 signals[WROTE_HEADERS] =
136 g_signal_new ("wrote_headers",
137 G_OBJECT_CLASS_TYPE (object_class),
139 G_STRUCT_OFFSET (SoupMessageClass, wrote_headers),
141 soup_marshal_NONE__NONE,
145 * SoupMessage::wrote-chunk:
148 * Emitted immediately after writing a body chunk for a message.
151 signals[WROTE_CHUNK] =
152 g_signal_new ("wrote_chunk",
153 G_OBJECT_CLASS_TYPE (object_class),
155 G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk),
157 soup_marshal_NONE__NONE,
161 * SoupMessage::wrote-body:
164 * Emitted immediately after writing the complete body for a message.
166 signals[WROTE_BODY] =
167 g_signal_new ("wrote_body",
168 G_OBJECT_CLASS_TYPE (object_class),
170 G_STRUCT_OFFSET (SoupMessageClass, wrote_body),
172 soup_marshal_NONE__NONE,
176 * SoupMessage::got-informational:
179 * Emitted after receiving a 1xx (Informational) response for
182 signals[GOT_INFORMATIONAL] =
183 g_signal_new ("got_informational",
184 G_OBJECT_CLASS_TYPE (object_class),
186 G_STRUCT_OFFSET (SoupMessageClass, got_informational),
188 soup_marshal_NONE__NONE,
192 * SoupMessage::got-headers:
195 * Emitted after receiving all message headers for a message.
197 signals[GOT_HEADERS] =
198 g_signal_new ("got_headers",
199 G_OBJECT_CLASS_TYPE (object_class),
201 G_STRUCT_OFFSET (SoupMessageClass, got_headers),
203 soup_marshal_NONE__NONE,
207 * SoupMessage::got-chunk:
210 * Emitted after receiving a chunk of a message body. Note
211 * that "chunk" in this context means any subpiece of the
212 * body, not necessarily the specific HTTP 1.1 chunks sent by
216 g_signal_new ("got_chunk",
217 G_OBJECT_CLASS_TYPE (object_class),
219 G_STRUCT_OFFSET (SoupMessageClass, got_chunk),
221 soup_marshal_NONE__NONE,
225 * SoupMessage::got-body:
228 * Emitted after receiving the complete message body.
231 g_signal_new ("got_body",
232 G_OBJECT_CLASS_TYPE (object_class),
234 G_STRUCT_OFFSET (SoupMessageClass, got_body),
236 soup_marshal_NONE__NONE,
240 * SoupMessage::restarted:
243 * Emitted when a message is about to be re-queued.
246 g_signal_new ("restarted",
247 G_OBJECT_CLASS_TYPE (object_class),
249 G_STRUCT_OFFSET (SoupMessageClass, restarted),
251 soup_marshal_NONE__NONE,
255 * SoupMessage::finished:
258 * Emitted when all HTTP processing is finished for a message.
259 * (After #read-body for client-side code, or after
260 * #wrote-body for server-side code.)
263 g_signal_new ("finished",
264 G_OBJECT_CLASS_TYPE (object_class),
266 G_STRUCT_OFFSET (SoupMessageClass, finished),
268 soup_marshal_NONE__NONE,
275 * @method: the HTTP method for the created request
276 * @uri_string: the destination endpoint (as a string)
278 * Creates a new empty #SoupMessage, which will connect to @uri
280 * Return value: the new #SoupMessage (or %NULL if @uri could not
284 soup_message_new (const char *method, const char *uri_string)
289 uri = soup_uri_new (uri_string);
298 msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
299 msg->method = method ? method : SOUP_METHOD_GET;
300 SOUP_MESSAGE_GET_PRIVATE (msg)->uri = uri;
306 * soup_message_new_from_uri:
307 * @method: the HTTP method for the created request
308 * @uri: the destination endpoint (as a #SoupUri)
310 * Creates a new empty #SoupMessage, which will connect to @uri
312 * Return value: the new #SoupMessage
315 soup_message_new_from_uri (const char *method, const SoupUri *uri)
319 msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
320 msg->method = method ? method : SOUP_METHOD_GET;
321 SOUP_MESSAGE_GET_PRIVATE (msg)->uri = soup_uri_copy (uri);
327 * soup_message_set_request:
329 * @content_type: MIME Content-Type of the body
330 * @req_owner: the #SoupOwnership of the passed data buffer.
331 * @req_body: a data buffer containing the body of the message request.
332 * @req_length: the byte length of @req_body.
334 * Convenience function to set the request body of a #SoupMessage
337 soup_message_set_request (SoupMessage *msg,
338 const char *content_type,
339 SoupOwnership req_owner,
343 g_return_if_fail (SOUP_IS_MESSAGE (msg));
344 g_return_if_fail (content_type != NULL);
345 g_return_if_fail (req_body != NULL || req_length == 0);
347 soup_message_add_header (msg->request_headers,
348 "Content-Type", content_type);
349 msg->request.owner = req_owner;
350 msg->request.body = req_body;
351 msg->request.length = req_length;
355 * soup_message_set_response:
357 * @content_type: MIME Content-Type of the body
358 * @resp_owner: the #SoupOwnership of the passed data buffer.
359 * @resp_body: a data buffer containing the body of the message response.
360 * @resp_length: the byte length of @resp_body.
362 * Convenience function to set the response body of a #SoupMessage
365 soup_message_set_response (SoupMessage *msg,
366 const char *content_type,
367 SoupOwnership resp_owner,
371 g_return_if_fail (SOUP_IS_MESSAGE (msg));
372 g_return_if_fail (content_type != NULL);
373 g_return_if_fail (resp_body != NULL || resp_length == 0);
375 soup_message_add_header (msg->response_headers,
376 "Content-Type", content_type);
377 msg->response.owner = resp_owner;
378 msg->response.body = resp_body;
379 msg->response.length = resp_length;
383 * soup_message_wrote_informational:
384 * @msg: a #SoupMessage
386 * Emits the %wrote_informational signal, indicating that the IO layer
387 * finished writing an informational (1xx) response for @msg.
390 soup_message_wrote_informational (SoupMessage *msg)
392 g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
396 * soup_message_wrote_headers:
397 * @msg: a #SoupMessage
399 * Emits the %wrote_headers signal, indicating that the IO layer
400 * finished writing the (non-informational) headers for @msg.
403 soup_message_wrote_headers (SoupMessage *msg)
405 g_signal_emit (msg, signals[WROTE_HEADERS], 0);
409 * soup_message_wrote_chunk:
410 * @msg: a #SoupMessage
412 * Emits the %wrote_chunk signal, indicating that the IO layer
413 * finished writing a chunk of @msg's body.
416 soup_message_wrote_chunk (SoupMessage *msg)
418 g_signal_emit (msg, signals[WROTE_CHUNK], 0);
422 wrote_body (SoupMessage *req)
425 soup_message_run_handlers (req, SOUP_HANDLER_POST_REQUEST);
426 g_object_unref (req);
430 * soup_message_wrote_body:
431 * @msg: a #SoupMessage
433 * Emits the %wrote_body signal, indicating that the IO layer finished
434 * writing the body for @msg.
437 soup_message_wrote_body (SoupMessage *msg)
439 g_signal_emit (msg, signals[WROTE_BODY], 0);
443 * soup_message_got_informational:
444 * @msg: a #SoupMessage
446 * Emits the %got_informational signal, indicating that the IO layer
447 * read a complete informational (1xx) response for @msg.
450 soup_message_got_informational (SoupMessage *msg)
452 g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
456 got_headers (SoupMessage *req)
459 soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY);
460 if (SOUP_MESSAGE_IS_STARTING (req))
461 g_signal_stop_emission (req, signals[GOT_HEADERS], 0);
462 g_object_unref (req);
466 * soup_message_got_headers:
467 * @msg: a #SoupMessage
469 * Emits the %got_headers signal, indicating that the IO layer
470 * finished reading the (non-informational) headers for @msg.
473 soup_message_got_headers (SoupMessage *msg)
475 g_signal_emit (msg, signals[GOT_HEADERS], 0);
479 got_chunk (SoupMessage *req)
482 soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK);
483 if (SOUP_MESSAGE_IS_STARTING (req))
484 g_signal_stop_emission (req, signals[GOT_CHUNK], 0);
485 g_object_unref (req);
489 * soup_message_got_chunk:
490 * @msg: a #SoupMessage
492 * Emits the %got_chunk signal, indicating that the IO layer finished
493 * reading a chunk of @msg's body.
496 soup_message_got_chunk (SoupMessage *msg)
498 g_signal_emit (msg, signals[GOT_CHUNK], 0);
502 got_body (SoupMessage *req)
505 soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
506 if (SOUP_MESSAGE_IS_STARTING (req))
507 g_signal_stop_emission (req, signals[GOT_BODY], 0);
508 g_object_unref (req);
512 * soup_message_got_body:
513 * @msg: a #SoupMessage
515 * Emits the %got_body signal, indicating that the IO layer finished
516 * reading the body for @msg.
519 soup_message_got_body (SoupMessage *msg)
521 g_signal_emit (msg, signals[GOT_BODY], 0);
525 restarted (SoupMessage *req)
527 soup_message_io_stop (req);
531 * soup_message_restarted:
532 * @msg: a #SoupMessage
534 * Emits the %restarted signal, indicating that @msg should be
538 soup_message_restarted (SoupMessage *msg)
540 g_signal_emit (msg, signals[RESTARTED], 0);
544 finished (SoupMessage *req)
546 soup_message_io_stop (req);
547 req->status = SOUP_MESSAGE_STATUS_FINISHED;
551 * soup_message_finished:
552 * @msg: a #SoupMessage
554 * Emits the %finished signal, indicating that @msg has been completely
558 soup_message_finished (SoupMessage *msg)
560 g_signal_emit (msg, signals[FINISHED], 0);
564 free_header_list (gpointer name, gpointer vals, gpointer user_data)
567 g_slist_foreach (vals, (GFunc) g_free, NULL);
574 * soup_message_clear_headers:
575 * @hash: a header table (the %request_headers or %response_headers
576 * field of a #SoupMessage)
581 soup_message_clear_headers (GHashTable *hash)
583 g_return_if_fail (hash != NULL);
585 g_hash_table_foreach_remove (hash, free_header_list, NULL);
589 * soup_message_remove_header:
590 * @hash: a header table (the %request_headers or %response_headers
591 * field of a #SoupMessage)
592 * @name: the header name to remove
594 * Removes @name from @hash. If there are multiple values for @name,
595 * they are all removed.
598 soup_message_remove_header (GHashTable *hash, const char *name)
600 gpointer old_key, old_vals;
602 g_return_if_fail (hash != NULL);
603 g_return_if_fail (name != NULL || name[0] != '\0');
605 if (g_hash_table_lookup_extended (hash, name, &old_key, &old_vals)) {
606 g_hash_table_remove (hash, name);
607 free_header_list (old_key, old_vals, NULL);
612 * soup_message_add_header:
613 * @hash: a header table (the %request_headers or %response_headers
614 * field of a #SoupMessage)
615 * @name: the header name to add
616 * @value: the value of the new header
618 * Adds a header with name @name and value @value to @hash. If there
619 * was already a header with name @name, this one does not replace it,
620 * it is merely added to it.
623 soup_message_add_header (GHashTable *hash, const char *name, const char *value)
627 g_return_if_fail (hash != NULL);
628 g_return_if_fail (name != NULL || name [0] != '\0');
629 g_return_if_fail (value != NULL);
631 old_value = g_hash_table_lookup (hash, name);
634 g_slist_append (old_value, g_strdup (value));
636 g_hash_table_insert (hash, g_strdup (name),
637 g_slist_append (NULL, g_strdup (value)));
642 * soup_message_get_header:
643 * @hash: a header table (the %request_headers or %response_headers
644 * field of a #SoupMessage)
645 * @name: header name.
647 * Finds the first header in @hash with name @name.
649 * Return value: the header's value or %NULL if not found.
652 soup_message_get_header (GHashTable *hash, const char *name)
656 g_return_val_if_fail (hash != NULL, NULL);
657 g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
659 vals = g_hash_table_lookup (hash, name);
667 * soup_message_get_header_list:
668 * @hash: a header table (the %request_headers or %response_headers
669 * field of a #SoupMessage)
670 * @name: header name.
672 * Finds all headers in @hash with name @name.
674 * Return value: a (possibly empty) list of values of headers with
675 * name @name. The caller should not modify or free this list.
678 soup_message_get_header_list (GHashTable *hash, const char *name)
680 g_return_val_if_fail (hash != NULL, NULL);
681 g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
683 return g_hash_table_lookup (hash, name);
689 } SoupMessageForeachHeaderData;
692 foreach_value_in_list (gpointer name, gpointer value, gpointer user_data)
694 GSList *vals = value;
695 SoupMessageForeachHeaderData *data = user_data;
698 (*data->func) (name, vals->data, data->user_data);
704 * soup_message_foreach_header:
705 * @hash: a header table (the %request_headers or %response_headers
706 * field of a #SoupMessage)
707 * @func: callback function to run for each header
708 * @user_data: data to pass to @func
710 * Calls @func once for each header value in @hash. (If there are
711 * headers will multiple values, @func will be called once on each
715 soup_message_foreach_header (GHashTable *hash, GHFunc func, gpointer user_data)
717 SoupMessageForeachHeaderData data;
719 g_return_if_fail (hash != NULL);
720 g_return_if_fail (func != NULL);
723 data.user_data = user_data;
724 g_hash_table_foreach (hash, foreach_value_in_list, &data);
728 * soup_message_cleanup_response:
729 * @req: a #SoupMessage
731 * Cleans up all response data on @req, so that the request can be sent
732 * again and receive a new response. (Eg, as a result of a redirect or
733 * authorization request.)
736 soup_message_cleanup_response (SoupMessage *req)
738 if (req->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
739 g_free (req->response.body);
741 req->response.owner = 0;
742 req->response.body = NULL;
743 req->response.length = 0;
747 soup_message_clear_headers (req->response_headers);
749 req->status_code = SOUP_STATUS_NONE;
750 if (req->reason_phrase) {
751 g_free ((char *) req->reason_phrase);
752 req->reason_phrase = NULL;
757 * soup_message_set_flags:
758 * @msg: a #SoupMessage
759 * @flags: a set of #SoupMessageFlags values
761 * Sets the specified flags on @msg.
764 soup_message_set_flags (SoupMessage *msg, guint flags)
766 g_return_if_fail (SOUP_IS_MESSAGE (msg));
768 SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags = flags;
772 * soup_message_get_flags:
773 * @msg: a #SoupMessage
775 * Gets the flags on @msg
777 * Return value: the flags
780 soup_message_get_flags (SoupMessage *msg)
782 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
784 return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags;
788 * soup_message_set_http_version:
789 * @msg: a #SoupMessage
790 * @version: the HTTP version
792 * Sets the HTTP version on @msg. The default version is
793 * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
794 * functionality from being used.
797 soup_message_set_http_version (SoupMessage *msg, SoupHttpVersion version)
799 g_return_if_fail (SOUP_IS_MESSAGE (msg));
801 SOUP_MESSAGE_GET_PRIVATE (msg)->http_version = version;
805 * soup_message_get_http_version:
806 * @msg: a #SoupMessage
808 * Gets the HTTP version of @msg. This is the minimum of the
809 * version from the request and the version from the response.
811 * Return value: the HTTP version
814 soup_message_get_http_version (SoupMessage *msg)
816 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0);
818 return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version;
822 * soup_message_is_keepalive:
823 * @msg: a #SoupMessage
825 * Determines whether or not @msg's connection can be kept alive for
826 * further requests after processing @msg.
828 * Return value: %TRUE or %FALSE.
831 soup_message_is_keepalive (SoupMessage *msg)
833 const char *c_conn, *s_conn;
835 c_conn = soup_message_get_header (msg->request_headers, "Connection");
836 s_conn = soup_message_get_header (msg->response_headers, "Connection");
838 if (msg->status_code == SOUP_STATUS_OK &&
839 soup_method_get_id (msg->method) == SOUP_METHOD_ID_CONNECT)
842 if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) {
843 /* Only persistent if the client requested keepalive
844 * and the server agreed.
847 if (!c_conn || !s_conn)
849 if (g_ascii_strcasecmp (c_conn, "Keep-Alive") != 0 ||
850 g_ascii_strcasecmp (s_conn, "Keep-Alive") != 0)
855 /* Normally persistent unless either side requested otherwise */
856 if (c_conn && g_ascii_strcasecmp (c_conn, "close") == 0)
858 if (s_conn && g_ascii_strcasecmp (s_conn, "close") == 0)
861 /* But not if the server sent a terminate-by-EOF response */
862 if (soup_message_get_response_encoding (msg, NULL) == SOUP_TRANSFER_EOF)
870 * soup_message_set_uri:
871 * @msg: a #SoupMessage
872 * @uri: the new #SoupUri
874 * Changes the URI that @msg is directed to (generally as a result
878 soup_message_set_uri (SoupMessage *msg, const SoupUri *uri)
880 SoupMessagePrivate *priv;
882 g_return_if_fail (SOUP_IS_MESSAGE (msg));
883 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
885 if (priv->uri && uri) {
886 if (strcmp (priv->uri->host, uri->host) != 0)
887 soup_message_io_stop (msg);
889 soup_message_io_stop (msg);
892 soup_uri_free (priv->uri);
893 priv->uri = soup_uri_copy (uri);
897 * soup_message_get_uri:
898 * @msg: a #SoupMessage
902 * Return value: the URI @msg is targeted for.
905 soup_message_get_uri (SoupMessage *msg)
907 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
909 return SOUP_MESSAGE_GET_PRIVATE (msg)->uri;
913 * soup_message_get_request_encoding:
914 * @msg: a #SoupMessage
915 * @content_length: a pointer to store the Content-Length in (or
918 * Gets @msg's request encoding. For an outgoing (client) request,
919 * this is only valid after the message has been fully set up (from
920 * the library's perspective, that means not until the message has
921 * been queued). For an incoming (server) request, this is valid after
922 * the request headers have been read and @msg->request_headers filled
925 * Return value: the request encoding (which cannot be
926 * %SOUP_TRANSFER_UNKNOWN or %SOUP_TRANSFER_EOF). If it is
927 * %SOUP_TRANSFER_CONTENT_LENGTH, *@content_length will be set to the
928 * request body's length.
931 soup_message_get_request_encoding (SoupMessage *msg, guint *content_length)
933 if (SOUP_IS_SERVER_MESSAGE (msg)) {
934 const char *enc, *len;
936 enc = soup_message_get_header (msg->request_headers,
937 "Transfer-Encoding");
938 len = soup_message_get_header (msg->request_headers,
941 if (g_ascii_strcasecmp (enc, "chunked") == 0)
942 return SOUP_TRANSFER_CHUNKED;
944 return SOUP_TRANSFER_UNKNOWN;
946 int lval = atoi (len);
949 return SOUP_TRANSFER_UNKNOWN;
952 *content_length = lval;
953 return SOUP_TRANSFER_CONTENT_LENGTH;
956 return SOUP_TRANSFER_NONE;
958 if (msg->request.length) {
960 *content_length = msg->request.length;
961 return SOUP_TRANSFER_CONTENT_LENGTH;
963 return SOUP_TRANSFER_NONE;
968 * soup_message_get_response_encoding:
969 * @msg: a #SoupMessage
970 * @content_length: a pointer to store the Content-Length in (or
973 * Gets @msg's response encoding. For an outgoing (client) request,
974 * this is only valid after the response headers have been read and
975 * @msg->response_headers filled in. For an incoming (server) request,
976 * this is valid after the server handler has run.
978 * Note that the returned value is the encoding actually used on the
979 * wire; this will not agree with the response headers in some cases
980 * (eg, a HEAD response may have a Content-Length header, but will
981 * still be considered %SOUP_TRANSFER_NONE by this function).
983 * Return value: the response encoding (which will not be
984 * %SOUP_TRANSFER_UNKNOWN). If it is %SOUP_TRANSFER_CONTENT_LENGTH,
985 * *@content_length will be set to the response body's length.
988 soup_message_get_response_encoding (SoupMessage *msg, guint *content_length)
990 SoupMethodId method = soup_method_get_id (msg->method);
992 /* FIXME: should CONNECT really be here? Where does it say that? */
993 if (method == SOUP_METHOD_ID_HEAD ||
994 method == SOUP_METHOD_ID_CONNECT ||
995 msg->status_code == SOUP_STATUS_NO_CONTENT ||
996 msg->status_code == SOUP_STATUS_NOT_MODIFIED ||
997 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code))
998 return SOUP_TRANSFER_NONE;
1000 if (SOUP_IS_SERVER_MESSAGE (msg)) {
1001 SoupTransferEncoding enc =
1002 soup_server_message_get_encoding ((SoupServerMessage *)msg);
1003 if (enc == SOUP_TRANSFER_UNKNOWN)
1004 enc = SOUP_TRANSFER_CONTENT_LENGTH;
1005 if (enc == SOUP_TRANSFER_CONTENT_LENGTH && content_length)
1006 *content_length = msg->response.length;
1009 const char *enc, *len;
1011 enc = soup_message_get_header (msg->response_headers,
1012 "Transfer-Encoding");
1013 len = soup_message_get_header (msg->response_headers,
1016 if (g_ascii_strcasecmp (enc, "chunked") == 0)
1017 return SOUP_TRANSFER_CHUNKED;
1019 return SOUP_TRANSFER_UNKNOWN;
1021 int lval = atoi (len);
1024 return SOUP_TRANSFER_UNKNOWN;
1027 *content_length = lval;
1028 return SOUP_TRANSFER_CONTENT_LENGTH;
1031 return SOUP_TRANSFER_EOF;
1036 * soup_message_set_status:
1037 * @msg: a #SoupMessage
1038 * @status_code: an HTTP status code
1040 * Sets @msg's status code to @status_code. If @status_code is a
1041 * known value, it will also set @msg's reason_phrase.
1044 soup_message_set_status (SoupMessage *msg, guint status_code)
1046 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1047 g_return_if_fail (status_code != 0);
1049 g_free ((char *) msg->reason_phrase);
1051 msg->status_code = status_code;
1052 msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code));
1056 * soup_message_set_status_full:
1057 * @msg: a #SoupMessage
1058 * @status_code: an HTTP status code
1059 * @reason_phrase: a description of the status
1061 * Sets @msg's status code and reason phrase.
1064 soup_message_set_status_full (SoupMessage *msg,
1066 const char *reason_phrase)
1068 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1069 g_return_if_fail (status_code != 0);
1070 g_return_if_fail (reason_phrase != NULL);
1072 g_free ((char *) msg->reason_phrase);
1074 msg->status_code = status_code;
1075 msg->reason_phrase = g_strdup (reason_phrase);
1080 * soup_message_add_chunk:
1081 * @msg: a #SoupMessage
1082 * @owner: the ownership of @body
1084 * @length: length of @body
1086 * Adds a chunk of response data to @body. (Note that currently
1087 * there is no way to send a request using chunked encoding.)
1090 soup_message_add_chunk (SoupMessage *msg,
1091 SoupOwnership owner,
1095 SoupMessagePrivate *priv;
1096 SoupDataBuffer *chunk;
1098 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1099 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1100 g_return_if_fail (body != NULL || length == 0);
1102 chunk = g_new0 (SoupDataBuffer, 1);
1103 if (owner == SOUP_BUFFER_USER_OWNED) {
1104 chunk->owner = SOUP_BUFFER_SYSTEM_OWNED;
1105 chunk->body = g_memdup (body, length);
1107 chunk->owner = owner;
1108 chunk->body = (char *)body;
1110 chunk->length = length;
1113 g_slist_append (priv->last_chunk, chunk);
1114 priv->last_chunk = priv->last_chunk->next;
1116 priv->chunks = priv->last_chunk =
1117 g_slist_append (NULL, chunk);
1122 * soup_message_add_final_chunk:
1123 * @msg: a #SoupMessage
1125 * Adds a final, empty chunk of response data to @body. This must
1126 * be called after adding the last real chunk, to indicate that
1127 * there is no more data.
1130 soup_message_add_final_chunk (SoupMessage *msg)
1132 soup_message_add_chunk (msg, SOUP_BUFFER_STATIC, NULL, 0);
1136 * soup_message_pop_chunk:
1137 * @msg: a #SoupMessage
1139 * Pops a chunk of response data from @msg's chunk list. The caller
1140 * must free @chunk itself, and must handle the data in @chunk
1141 * according to its %ownership.
1143 * Return value: the chunk, or %NULL if there are no chunks left.
1146 soup_message_pop_chunk (SoupMessage *msg)
1148 SoupMessagePrivate *priv;
1149 SoupDataBuffer *chunk;
1151 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1152 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1157 chunk = priv->chunks->data;
1158 priv->chunks = g_slist_remove (priv->chunks, chunk);
1160 priv->last_chunk = NULL;
1166 free_chunks (SoupMessage *msg)
1168 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1169 SoupDataBuffer *chunk;
1172 for (ch = priv->chunks; ch; ch = ch->next) {
1175 if (chunk->owner == SOUP_BUFFER_SYSTEM_OWNED)
1176 g_free (chunk->body);
1180 g_slist_free (priv->chunks);
1181 priv->chunks = priv->last_chunk = NULL;