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_cleanup (msg);
71 soup_uri_free (priv->uri);
74 g_object_unref (priv->auth);
76 g_object_unref (priv->proxy_auth);
78 if (msg->request.owner == SOUP_BUFFER_SYSTEM_OWNED)
79 g_free (msg->request.body);
80 if (msg->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
81 g_free (msg->response.body);
84 soup_message_clear_headers (msg->request_headers);
85 g_hash_table_destroy (msg->request_headers);
87 soup_message_clear_headers (msg->response_headers);
88 g_hash_table_destroy (msg->response_headers);
90 g_slist_foreach (priv->content_handlers, (GFunc) g_free, NULL);
91 g_slist_free (priv->content_handlers);
93 g_free ((char *) msg->reason_phrase);
95 G_OBJECT_CLASS (soup_message_parent_class)->finalize (object);
99 soup_message_class_init (SoupMessageClass *message_class)
101 GObjectClass *object_class = G_OBJECT_CLASS (message_class);
103 g_type_class_add_private (message_class, sizeof (SoupMessagePrivate));
105 /* virtual method definition */
106 message_class->wrote_body = wrote_body;
107 message_class->got_headers = got_headers;
108 message_class->got_chunk = got_chunk;
109 message_class->got_body = got_body;
110 message_class->restarted = restarted;
111 message_class->finished = finished;
113 /* virtual method override */
114 object_class->finalize = finalize;
119 * SoupMessage::wrote-informational:
122 * Emitted immediately after writing a 1xx (Informational)
123 * response for a message.
125 signals[WROTE_INFORMATIONAL] =
126 g_signal_new ("wrote_informational",
127 G_OBJECT_CLASS_TYPE (object_class),
129 G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
131 soup_marshal_NONE__NONE,
135 * SoupMessage::wrote-headers:
138 * Emitted immediately after writing the headers for a message.
140 signals[WROTE_HEADERS] =
141 g_signal_new ("wrote_headers",
142 G_OBJECT_CLASS_TYPE (object_class),
144 G_STRUCT_OFFSET (SoupMessageClass, wrote_headers),
146 soup_marshal_NONE__NONE,
150 * SoupMessage::wrote-chunk:
153 * Emitted immediately after writing a body chunk for a message.
155 signals[WROTE_CHUNK] =
156 g_signal_new ("wrote_chunk",
157 G_OBJECT_CLASS_TYPE (object_class),
159 G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk),
161 soup_marshal_NONE__NONE,
165 * SoupMessage::wrote-body:
168 * Emitted immediately after writing the complete body for a message.
170 signals[WROTE_BODY] =
171 g_signal_new ("wrote_body",
172 G_OBJECT_CLASS_TYPE (object_class),
174 G_STRUCT_OFFSET (SoupMessageClass, wrote_body),
176 soup_marshal_NONE__NONE,
180 * SoupMessage::got-informational:
183 * Emitted after receiving a 1xx (Informational) response for
186 signals[GOT_INFORMATIONAL] =
187 g_signal_new ("got_informational",
188 G_OBJECT_CLASS_TYPE (object_class),
190 G_STRUCT_OFFSET (SoupMessageClass, got_informational),
192 soup_marshal_NONE__NONE,
196 * SoupMessage::got-headers:
199 * Emitted after receiving all message headers for a message.
201 signals[GOT_HEADERS] =
202 g_signal_new ("got_headers",
203 G_OBJECT_CLASS_TYPE (object_class),
205 G_STRUCT_OFFSET (SoupMessageClass, got_headers),
207 soup_marshal_NONE__NONE,
211 * SoupMessage::got-chunk:
214 * Emitted after receiving a chunk of a message body. Note
215 * that "chunk" in this context means any subpiece of the
216 * body, not necessarily the specific HTTP 1.1 chunks sent by
220 g_signal_new ("got_chunk",
221 G_OBJECT_CLASS_TYPE (object_class),
223 G_STRUCT_OFFSET (SoupMessageClass, got_chunk),
225 soup_marshal_NONE__NONE,
229 * SoupMessage::got-body:
232 * Emitted after receiving the complete message body.
235 g_signal_new ("got_body",
236 G_OBJECT_CLASS_TYPE (object_class),
238 G_STRUCT_OFFSET (SoupMessageClass, got_body),
240 soup_marshal_NONE__NONE,
244 * SoupMessage::restarted:
247 * Emitted when a message is about to be re-queued.
250 g_signal_new ("restarted",
251 G_OBJECT_CLASS_TYPE (object_class),
253 G_STRUCT_OFFSET (SoupMessageClass, restarted),
255 soup_marshal_NONE__NONE,
259 * SoupMessage::finished:
262 * Emitted when all HTTP processing is finished for a message.
263 * (After #read-body for client-side code, or after
264 * #wrote-body for server-side code.)
267 g_signal_new ("finished",
268 G_OBJECT_CLASS_TYPE (object_class),
270 G_STRUCT_OFFSET (SoupMessageClass, finished),
272 soup_marshal_NONE__NONE,
279 * @method: the HTTP method for the created request
280 * @uri_string: the destination endpoint (as a string)
282 * Creates a new empty #SoupMessage, which will connect to @uri
284 * Return value: the new #SoupMessage (or %NULL if @uri could not
288 soup_message_new (const char *method, const char *uri_string)
293 uri = soup_uri_new (uri_string);
302 msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
303 msg->method = method ? method : SOUP_METHOD_GET;
304 SOUP_MESSAGE_GET_PRIVATE (msg)->uri = uri;
310 * soup_message_new_from_uri:
311 * @method: the HTTP method for the created request
312 * @uri: the destination endpoint (as a #SoupUri)
314 * Creates a new empty #SoupMessage, which will connect to @uri
316 * Return value: the new #SoupMessage
319 soup_message_new_from_uri (const char *method, const SoupUri *uri)
323 msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
324 msg->method = method ? method : SOUP_METHOD_GET;
325 SOUP_MESSAGE_GET_PRIVATE (msg)->uri = soup_uri_copy (uri);
331 * soup_message_set_request:
333 * @content_type: MIME Content-Type of the body
334 * @req_owner: the #SoupOwnership of the passed data buffer.
335 * @req_body: a data buffer containing the body of the message request.
336 * @req_length: the byte length of @req_body.
338 * Convenience function to set the request body of a #SoupMessage
341 soup_message_set_request (SoupMessage *msg,
342 const char *content_type,
343 SoupOwnership req_owner,
347 g_return_if_fail (SOUP_IS_MESSAGE (msg));
348 g_return_if_fail (content_type != NULL);
349 g_return_if_fail (req_body != NULL || req_length == 0);
351 soup_message_add_header (msg->request_headers,
352 "Content-Type", content_type);
353 msg->request.owner = req_owner;
354 msg->request.body = req_body;
355 msg->request.length = req_length;
359 * soup_message_set_response:
361 * @content_type: MIME Content-Type of the body
362 * @resp_owner: the #SoupOwnership of the passed data buffer.
363 * @resp_body: a data buffer containing the body of the message response.
364 * @resp_length: the byte length of @resp_body.
366 * Convenience function to set the response body of a #SoupMessage
369 soup_message_set_response (SoupMessage *msg,
370 const char *content_type,
371 SoupOwnership resp_owner,
375 g_return_if_fail (SOUP_IS_MESSAGE (msg));
376 g_return_if_fail (content_type != NULL);
377 g_return_if_fail (resp_body != NULL || resp_length == 0);
379 soup_message_add_header (msg->response_headers,
380 "Content-Type", content_type);
381 msg->response.owner = resp_owner;
382 msg->response.body = resp_body;
383 msg->response.length = resp_length;
387 * soup_message_wrote_informational:
388 * @msg: a #SoupMessage
390 * Emits the %wrote_informational signal, indicating that the IO layer
391 * finished writing an informational (1xx) response for @msg.
394 soup_message_wrote_informational (SoupMessage *msg)
396 g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
400 * soup_message_wrote_headers:
401 * @msg: a #SoupMessage
403 * Emits the %wrote_headers signal, indicating that the IO layer
404 * finished writing the (non-informational) headers for @msg.
407 soup_message_wrote_headers (SoupMessage *msg)
409 g_signal_emit (msg, signals[WROTE_HEADERS], 0);
413 * soup_message_wrote_chunk:
414 * @msg: a #SoupMessage
416 * Emits the %wrote_chunk signal, indicating that the IO layer
417 * finished writing a chunk of @msg's body.
420 soup_message_wrote_chunk (SoupMessage *msg)
422 g_signal_emit (msg, signals[WROTE_CHUNK], 0);
426 wrote_body (SoupMessage *req)
429 soup_message_run_handlers (req, SOUP_HANDLER_POST_REQUEST);
430 g_object_unref (req);
434 * soup_message_wrote_body:
435 * @msg: a #SoupMessage
437 * Emits the %wrote_body signal, indicating that the IO layer finished
438 * writing the body for @msg.
441 soup_message_wrote_body (SoupMessage *msg)
443 g_signal_emit (msg, signals[WROTE_BODY], 0);
447 * soup_message_got_informational:
448 * @msg: a #SoupMessage
450 * Emits the %got_informational signal, indicating that the IO layer
451 * read a complete informational (1xx) response for @msg.
454 soup_message_got_informational (SoupMessage *msg)
456 g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
460 got_headers (SoupMessage *req)
463 soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY);
464 if (SOUP_MESSAGE_IS_STARTING (req))
465 g_signal_stop_emission (req, signals[GOT_HEADERS], 0);
466 g_object_unref (req);
470 * soup_message_got_headers:
471 * @msg: a #SoupMessage
473 * Emits the %got_headers signal, indicating that the IO layer
474 * finished reading the (non-informational) headers for @msg.
477 soup_message_got_headers (SoupMessage *msg)
479 g_signal_emit (msg, signals[GOT_HEADERS], 0);
483 got_chunk (SoupMessage *req)
486 soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK);
487 if (SOUP_MESSAGE_IS_STARTING (req))
488 g_signal_stop_emission (req, signals[GOT_CHUNK], 0);
489 g_object_unref (req);
493 * soup_message_got_chunk:
494 * @msg: a #SoupMessage
496 * Emits the %got_chunk signal, indicating that the IO layer finished
497 * reading a chunk of @msg's body.
500 soup_message_got_chunk (SoupMessage *msg)
502 g_signal_emit (msg, signals[GOT_CHUNK], 0);
506 got_body (SoupMessage *req)
509 soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
510 if (SOUP_MESSAGE_IS_STARTING (req))
511 g_signal_stop_emission (req, signals[GOT_BODY], 0);
512 g_object_unref (req);
516 * soup_message_got_body:
517 * @msg: a #SoupMessage
519 * Emits the %got_body signal, indicating that the IO layer finished
520 * reading the body for @msg.
523 soup_message_got_body (SoupMessage *msg)
525 g_signal_emit (msg, signals[GOT_BODY], 0);
529 restarted (SoupMessage *req)
531 soup_message_io_stop (req);
535 * soup_message_restarted:
536 * @msg: a #SoupMessage
538 * Emits the %restarted signal, indicating that @msg should be
542 soup_message_restarted (SoupMessage *msg)
544 g_signal_emit (msg, signals[RESTARTED], 0);
548 finished (SoupMessage *req)
550 soup_message_io_stop (req);
551 req->status = SOUP_MESSAGE_STATUS_FINISHED;
555 * soup_message_finished:
556 * @msg: a #SoupMessage
558 * Emits the %finished signal, indicating that @msg has been completely
562 soup_message_finished (SoupMessage *msg)
564 g_signal_emit (msg, signals[FINISHED], 0);
568 free_header_list (gpointer name, gpointer vals, gpointer user_data)
571 g_slist_foreach (vals, (GFunc) g_free, NULL);
578 * soup_message_clear_headers:
579 * @hash: a header table (the %request_headers or %response_headers
580 * field of a #SoupMessage)
585 soup_message_clear_headers (GHashTable *hash)
587 g_return_if_fail (hash != NULL);
589 g_hash_table_foreach_remove (hash, free_header_list, NULL);
593 * soup_message_remove_header:
594 * @hash: a header table (the %request_headers or %response_headers
595 * field of a #SoupMessage)
596 * @name: the header name to remove
598 * Removes @name from @hash. If there are multiple values for @name,
599 * they are all removed.
602 soup_message_remove_header (GHashTable *hash, const char *name)
604 gpointer old_key, old_vals;
606 g_return_if_fail (hash != NULL);
607 g_return_if_fail (name != NULL || name[0] != '\0');
609 if (g_hash_table_lookup_extended (hash, name, &old_key, &old_vals)) {
610 g_hash_table_remove (hash, name);
611 free_header_list (old_key, old_vals, NULL);
616 * soup_message_add_header:
617 * @hash: a header table (the %request_headers or %response_headers
618 * field of a #SoupMessage)
619 * @name: the header name to add
620 * @value: the value of the new header
622 * Adds a header with name @name and value @value to @hash. If there
623 * was already a header with name @name, this one does not replace it,
624 * it is merely added to it.
627 soup_message_add_header (GHashTable *hash, const char *name, const char *value)
631 g_return_if_fail (hash != NULL);
632 g_return_if_fail (name != NULL || name [0] != '\0');
633 g_return_if_fail (value != NULL);
635 old_value = g_hash_table_lookup (hash, name);
638 old_value = g_slist_append (old_value, g_strdup (value));
640 g_hash_table_insert (hash, g_strdup (name),
641 g_slist_append (NULL, g_strdup (value)));
646 * soup_message_get_header:
647 * @hash: a header table (the %request_headers or %response_headers
648 * field of a #SoupMessage)
649 * @name: header name.
651 * Finds the first header in @hash with name @name.
653 * Return value: the header's value or %NULL if not found.
656 soup_message_get_header (GHashTable *hash, const char *name)
660 g_return_val_if_fail (hash != NULL, NULL);
661 g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
663 vals = g_hash_table_lookup (hash, name);
671 * soup_message_get_header_list:
672 * @hash: a header table (the %request_headers or %response_headers
673 * field of a #SoupMessage)
674 * @name: header name.
676 * Finds all headers in @hash with name @name.
678 * Return value: a (possibly empty) list of values of headers with
679 * name @name. The caller should not modify or free this list.
682 soup_message_get_header_list (GHashTable *hash, const char *name)
684 g_return_val_if_fail (hash != NULL, NULL);
685 g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
687 return g_hash_table_lookup (hash, name);
693 } SoupMessageForeachHeaderData;
696 foreach_value_in_list (gpointer name, gpointer value, gpointer user_data)
698 GSList *vals = value;
699 SoupMessageForeachHeaderData *data = user_data;
702 (*data->func) (name, vals->data, data->user_data);
708 * soup_message_foreach_header:
709 * @hash: a header table (the %request_headers or %response_headers
710 * field of a #SoupMessage)
711 * @func: callback function to run for each header
712 * @user_data: data to pass to @func
714 * Calls @func once for each header value in @hash. (If there are
715 * headers will multiple values, @func will be called once on each
719 soup_message_foreach_header (GHashTable *hash, GHFunc func, gpointer user_data)
721 SoupMessageForeachHeaderData data;
723 g_return_if_fail (hash != NULL);
724 g_return_if_fail (func != NULL);
727 data.user_data = user_data;
728 g_hash_table_foreach (hash, foreach_value_in_list, &data);
732 * soup_message_set_auth:
733 * @msg: a #SoupMessage
734 * @auth: a #SoupAuth, or %NULL
736 * Sets @msg to authenticate to its destination using @auth, which
737 * must have already been fully authenticated. If @auth is %NULL, @msg
738 * will not authenticate to its destination.
741 soup_message_set_auth (SoupMessage *msg, SoupAuth *auth)
743 SoupMessagePrivate *priv;
746 g_return_if_fail (SOUP_IS_MESSAGE (msg));
747 g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
748 g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
750 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
753 g_object_unref (priv->auth);
754 soup_message_remove_header (msg->request_headers, "Authorization");
760 g_object_ref (priv->auth);
761 token = soup_auth_get_authorization (auth, msg);
762 soup_message_add_header (msg->request_headers, "Authorization", token);
767 * soup_message_get_auth:
768 * @msg: a #SoupMessage
770 * Gets the #SoupAuth used by @msg for authentication.
772 * Return value: the #SoupAuth used by @msg for authentication, or
773 * %NULL if @msg is unauthenticated.
776 soup_message_get_auth (SoupMessage *msg)
778 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
780 return SOUP_MESSAGE_GET_PRIVATE (msg)->auth;
784 * soup_message_set_proxy_auth:
785 * @msg: a #SoupMessage
786 * @auth: a #SoupAuth, or %NULL
788 * Sets @msg to authenticate to its proxy using @auth, which must have
789 * already been fully authenticated. If @auth is %NULL, @msg will not
790 * authenticate to its proxy.
793 soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth)
795 SoupMessagePrivate *priv;
798 g_return_if_fail (SOUP_IS_MESSAGE (msg));
799 g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
800 g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
802 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
804 if (priv->proxy_auth) {
805 g_object_unref (priv->proxy_auth);
806 soup_message_remove_header (msg->request_headers,
807 "Proxy-Authorization");
809 priv->proxy_auth = auth;
810 if (!priv->proxy_auth)
813 g_object_ref (priv->proxy_auth);
814 token = soup_auth_get_authorization (auth, msg);
815 soup_message_add_header (msg->request_headers,
816 "Proxy-Authorization", token);
821 * soup_message_get_proxy_auth:
822 * @msg: a #SoupMessage
824 * Gets the #SoupAuth used by @msg for authentication to its proxy..
826 * Return value: the #SoupAuth used by @msg for authentication to its
827 * proxy, or %NULL if @msg isn't authenticated to its proxy.
830 soup_message_get_proxy_auth (SoupMessage *msg)
832 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
834 return SOUP_MESSAGE_GET_PRIVATE (msg)->proxy_auth;
838 * soup_message_cleanup_response:
839 * @req: a #SoupMessage
841 * Cleans up all response data on @req, so that the request can be sent
842 * again and receive a new response. (Eg, as a result of a redirect or
843 * authorization request.)
846 soup_message_cleanup_response (SoupMessage *req)
848 if (req->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
849 g_free (req->response.body);
851 req->response.owner = 0;
852 req->response.body = NULL;
853 req->response.length = 0;
857 soup_message_clear_headers (req->response_headers);
859 req->status_code = SOUP_STATUS_NONE;
860 if (req->reason_phrase) {
861 g_free ((char *) req->reason_phrase);
862 req->reason_phrase = NULL;
867 * soup_message_set_flags:
868 * @msg: a #SoupMessage
869 * @flags: a set of #SoupMessageFlags values
871 * Sets the specified flags on @msg.
874 soup_message_set_flags (SoupMessage *msg, guint flags)
876 g_return_if_fail (SOUP_IS_MESSAGE (msg));
878 SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags = flags;
882 * soup_message_get_flags:
883 * @msg: a #SoupMessage
885 * Gets the flags on @msg
887 * Return value: the flags
890 soup_message_get_flags (SoupMessage *msg)
892 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
894 return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags;
898 * soup_message_set_http_version:
899 * @msg: a #SoupMessage
900 * @version: the HTTP version
902 * Sets the HTTP version on @msg. The default version is
903 * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
904 * functionality from being used.
907 soup_message_set_http_version (SoupMessage *msg, SoupHttpVersion version)
909 g_return_if_fail (SOUP_IS_MESSAGE (msg));
911 SOUP_MESSAGE_GET_PRIVATE (msg)->http_version = version;
915 * soup_message_get_http_version:
916 * @msg: a #SoupMessage
918 * Gets the HTTP version of @msg. This is the minimum of the
919 * version from the request and the version from the response.
921 * Return value: the HTTP version
924 soup_message_get_http_version (SoupMessage *msg)
926 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0);
928 return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version;
932 * soup_message_is_keepalive:
933 * @msg: a #SoupMessage
935 * Determines whether or not @msg's connection can be kept alive for
936 * further requests after processing @msg.
938 * Return value: %TRUE or %FALSE.
941 soup_message_is_keepalive (SoupMessage *msg)
943 const char *c_conn, *s_conn;
945 c_conn = soup_message_get_header (msg->request_headers, "Connection");
946 s_conn = soup_message_get_header (msg->response_headers, "Connection");
948 if (msg->status_code == SOUP_STATUS_OK &&
949 soup_method_get_id (msg->method) == SOUP_METHOD_ID_CONNECT)
952 if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) {
953 /* Only persistent if the client requested keepalive
954 * and the server agreed.
957 if (!c_conn || !s_conn)
959 if (g_ascii_strcasecmp (c_conn, "Keep-Alive") != 0 ||
960 g_ascii_strcasecmp (s_conn, "Keep-Alive") != 0)
965 /* Normally persistent unless either side requested otherwise */
966 if (c_conn && g_ascii_strcasecmp (c_conn, "close") == 0)
968 if (s_conn && g_ascii_strcasecmp (s_conn, "close") == 0)
971 /* But not if the server sent a terminate-by-EOF response */
972 if (soup_message_get_response_encoding (msg, NULL) == SOUP_TRANSFER_EOF)
980 * soup_message_set_uri:
981 * @msg: a #SoupMessage
982 * @uri: the new #SoupUri
984 * Sets @msg's URI to @uri. If @msg has already been sent and you want
985 * to re-send it with the new URI, you need to call
986 * soup_session_requeue_message().
989 soup_message_set_uri (SoupMessage *msg, const SoupUri *uri)
991 SoupMessagePrivate *priv;
993 g_return_if_fail (SOUP_IS_MESSAGE (msg));
994 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
997 soup_uri_free (priv->uri);
998 priv->uri = soup_uri_copy (uri);
1002 * soup_message_get_uri:
1003 * @msg: a #SoupMessage
1007 * Return value: the URI @msg is targeted for.
1010 soup_message_get_uri (SoupMessage *msg)
1012 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1014 return SOUP_MESSAGE_GET_PRIVATE (msg)->uri;
1018 * soup_message_get_request_encoding:
1019 * @msg: a #SoupMessage
1020 * @content_length: a pointer to store the Content-Length in (or
1023 * Gets @msg's request encoding. For an outgoing (client) request,
1024 * this is only valid after the message has been fully set up (from
1025 * the library's perspective, that means not until the message has
1026 * been queued). For an incoming (server) request, this is valid after
1027 * the request headers have been read and @msg->request_headers filled
1030 * Return value: the request encoding (which cannot be
1031 * %SOUP_TRANSFER_UNKNOWN or %SOUP_TRANSFER_EOF). If it is
1032 * %SOUP_TRANSFER_CONTENT_LENGTH, *@content_length will be set to the
1033 * request body's length.
1035 SoupTransferEncoding
1036 soup_message_get_request_encoding (SoupMessage *msg, guint *content_length)
1038 if (SOUP_IS_SERVER_MESSAGE (msg)) {
1039 const char *enc, *len;
1041 enc = soup_message_get_header (msg->request_headers,
1042 "Transfer-Encoding");
1043 len = soup_message_get_header (msg->request_headers,
1046 if (g_ascii_strcasecmp (enc, "chunked") == 0)
1047 return SOUP_TRANSFER_CHUNKED;
1049 return SOUP_TRANSFER_UNKNOWN;
1051 int lval = atoi (len);
1054 return SOUP_TRANSFER_UNKNOWN;
1057 *content_length = lval;
1058 return SOUP_TRANSFER_CONTENT_LENGTH;
1061 return SOUP_TRANSFER_NONE;
1063 if (msg->request.length) {
1065 *content_length = msg->request.length;
1066 return SOUP_TRANSFER_CONTENT_LENGTH;
1068 return SOUP_TRANSFER_NONE;
1073 * soup_message_get_response_encoding:
1074 * @msg: a #SoupMessage
1075 * @content_length: a pointer to store the Content-Length in (or
1078 * Gets @msg's response encoding. For an outgoing (client) request,
1079 * this is only valid after the response headers have been read and
1080 * @msg->response_headers filled in. For an incoming (server) request,
1081 * this is valid after the server handler has run.
1083 * Note that the returned value is the encoding actually used on the
1084 * wire; this will not agree with the response headers in some cases
1085 * (eg, a HEAD response may have a Content-Length header, but will
1086 * still be considered %SOUP_TRANSFER_NONE by this function).
1088 * Return value: the response encoding (which will not be
1089 * %SOUP_TRANSFER_UNKNOWN). If it is %SOUP_TRANSFER_CONTENT_LENGTH,
1090 * *@content_length will be set to the response body's length.
1092 SoupTransferEncoding
1093 soup_message_get_response_encoding (SoupMessage *msg, guint *content_length)
1095 SoupMethodId method = soup_method_get_id (msg->method);
1097 if (method == SOUP_METHOD_ID_HEAD ||
1098 msg->status_code == SOUP_STATUS_NO_CONTENT ||
1099 msg->status_code == SOUP_STATUS_NOT_MODIFIED ||
1100 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code))
1101 return SOUP_TRANSFER_NONE;
1103 if (SOUP_IS_SERVER_MESSAGE (msg)) {
1104 SoupTransferEncoding enc =
1105 soup_server_message_get_encoding ((SoupServerMessage *)msg);
1106 if (enc == SOUP_TRANSFER_UNKNOWN)
1107 enc = SOUP_TRANSFER_CONTENT_LENGTH;
1108 if (enc == SOUP_TRANSFER_CONTENT_LENGTH && content_length)
1109 *content_length = msg->response.length;
1112 const char *enc, *len;
1114 enc = soup_message_get_header (msg->response_headers,
1115 "Transfer-Encoding");
1116 len = soup_message_get_header (msg->response_headers,
1119 if (g_ascii_strcasecmp (enc, "chunked") == 0)
1120 return SOUP_TRANSFER_CHUNKED;
1122 return SOUP_TRANSFER_UNKNOWN;
1124 int lval = atoi (len);
1127 return SOUP_TRANSFER_UNKNOWN;
1130 *content_length = lval;
1131 return SOUP_TRANSFER_CONTENT_LENGTH;
1133 } else if (method == SOUP_METHOD_ID_CONNECT)
1134 return SOUP_TRANSFER_NONE;
1136 return SOUP_TRANSFER_EOF;
1141 * soup_message_set_status:
1142 * @msg: a #SoupMessage
1143 * @status_code: an HTTP status code
1145 * Sets @msg's status code to @status_code. If @status_code is a
1146 * known value, it will also set @msg's reason_phrase.
1149 soup_message_set_status (SoupMessage *msg, guint status_code)
1151 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1152 g_return_if_fail (status_code != 0);
1154 g_free ((char *) msg->reason_phrase);
1156 msg->status_code = status_code;
1157 msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code));
1161 * soup_message_set_status_full:
1162 * @msg: a #SoupMessage
1163 * @status_code: an HTTP status code
1164 * @reason_phrase: a description of the status
1166 * Sets @msg's status code and reason phrase.
1169 soup_message_set_status_full (SoupMessage *msg,
1171 const char *reason_phrase)
1173 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1174 g_return_if_fail (status_code != 0);
1175 g_return_if_fail (reason_phrase != NULL);
1177 g_free ((char *) msg->reason_phrase);
1179 msg->status_code = status_code;
1180 msg->reason_phrase = g_strdup (reason_phrase);
1185 * soup_message_add_chunk:
1186 * @msg: a #SoupMessage
1187 * @owner: the ownership of @body
1189 * @length: length of @body
1191 * Adds a chunk of response data to @body. (Note that currently
1192 * there is no way to send a request using chunked encoding.)
1195 soup_message_add_chunk (SoupMessage *msg,
1196 SoupOwnership owner,
1200 SoupMessagePrivate *priv;
1201 SoupDataBuffer *chunk;
1203 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1204 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1205 g_return_if_fail (body != NULL || length == 0);
1207 chunk = g_new0 (SoupDataBuffer, 1);
1208 if (owner == SOUP_BUFFER_USER_OWNED) {
1209 chunk->owner = SOUP_BUFFER_SYSTEM_OWNED;
1210 chunk->body = g_memdup (body, length);
1212 chunk->owner = owner;
1213 chunk->body = (char *)body;
1215 chunk->length = length;
1218 priv->last_chunk = g_slist_append (priv->last_chunk, chunk);
1219 priv->last_chunk = priv->last_chunk->next;
1221 priv->chunks = priv->last_chunk =
1222 g_slist_append (NULL, chunk);
1227 * soup_message_add_final_chunk:
1228 * @msg: a #SoupMessage
1230 * Adds a final, empty chunk of response data to @body. This must
1231 * be called after adding the last real chunk, to indicate that
1232 * there is no more data.
1235 soup_message_add_final_chunk (SoupMessage *msg)
1237 soup_message_add_chunk (msg, SOUP_BUFFER_STATIC, NULL, 0);
1241 * soup_message_pop_chunk:
1242 * @msg: a #SoupMessage
1244 * Pops a chunk of response data from @msg's chunk list. The caller
1245 * must free @chunk itself, and must handle the data in @chunk
1246 * according to its %ownership.
1248 * Return value: the chunk, or %NULL if there are no chunks left.
1251 soup_message_pop_chunk (SoupMessage *msg)
1253 SoupMessagePrivate *priv;
1254 SoupDataBuffer *chunk;
1256 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1257 priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1262 chunk = priv->chunks->data;
1263 priv->chunks = g_slist_remove (priv->chunks, chunk);
1265 priv->last_chunk = NULL;
1271 free_chunks (SoupMessage *msg)
1273 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1274 SoupDataBuffer *chunk;
1277 for (ch = priv->chunks; ch; ch = ch->next) {
1280 if (chunk->owner == SOUP_BUFFER_SYSTEM_OWNED)
1281 g_free (chunk->body);
1285 g_slist_free (priv->chunks);
1286 priv->chunks = priv->last_chunk = NULL;