1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-message-client-io.c: client-side request/response
5 * Copyright (C) 2000-2003, Ximian, Inc.
14 #include <glib/gi18n-lib.h>
17 #include "soup-connection.h"
18 #include "soup-message-private.h"
19 #include "soup-message-queue.h"
20 #include "soup-misc-private.h"
23 parse_response_headers (SoupMessage *msg,
24 char *headers, guint headers_len,
25 SoupEncoding *encoding,
29 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
30 SoupHTTPVersion version;
32 g_free(msg->reason_phrase);
33 msg->reason_phrase = NULL;
34 if (!soup_headers_parse_response (headers, headers_len,
35 msg->response_headers,
38 &msg->reason_phrase)) {
39 g_set_error_literal (error, SOUP_REQUEST_ERROR,
40 SOUP_REQUEST_ERROR_PARSING,
41 _("Could not parse HTTP response"));
42 return SOUP_STATUS_MALFORMED;
45 g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
46 g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
48 if (version < priv->http_version) {
49 priv->http_version = version;
50 g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION);
53 if ((msg->method == SOUP_METHOD_HEAD ||
54 msg->status_code == SOUP_STATUS_NO_CONTENT ||
55 msg->status_code == SOUP_STATUS_NOT_MODIFIED ||
56 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) ||
57 (msg->method == SOUP_METHOD_CONNECT &&
58 SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)))
59 *encoding = SOUP_ENCODING_NONE;
61 *encoding = soup_message_headers_get_encoding (msg->response_headers);
63 if (*encoding == SOUP_ENCODING_UNRECOGNIZED) {
64 g_set_error_literal (error, SOUP_REQUEST_ERROR,
65 SOUP_REQUEST_ERROR_ENCODING,
66 _("Unrecognized HTTP response encoding"));
67 return SOUP_STATUS_MALFORMED;
70 return SOUP_STATUS_OK;
74 get_request_headers (SoupMessage *msg, GString *header,
75 SoupEncoding *encoding, gpointer user_data)
77 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
78 SoupMessageQueueItem *item = user_data;
79 SoupURI *uri = soup_message_get_uri (msg);
82 SoupMessageHeadersIter iter;
83 const char *name, *value;
85 if (strchr (uri->host, ':'))
86 uri_host = g_strdup_printf ("[%.*s]", (int) strcspn (uri->host, "%"), uri->host);
87 else if (g_hostname_is_non_ascii (uri->host))
88 uri_host = g_hostname_to_ascii (uri->host);
92 if (msg->method == SOUP_METHOD_CONNECT) {
93 /* CONNECT URI is hostname:port for tunnel destination */
94 uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port);
96 gboolean proxy = soup_connection_is_via_proxy (item->conn);
98 /* Proxy expects full URI to destination. Otherwise
101 uri_string = soup_uri_to_string (uri, !proxy);
103 if (proxy && uri->fragment) {
105 char *fragment = strchr (uri_string, '#');
111 g_string_append_printf (header, "%s %s HTTP/1.%d\r\n",
112 msg->method, uri_string,
113 (priv->http_version == SOUP_HTTP_1_0) ? 0 : 1);
115 if (!soup_message_headers_get_one (msg->request_headers, "Host")) {
116 if (soup_uri_uses_default_port (uri)) {
117 g_string_append_printf (header, "Host: %s\r\n",
120 g_string_append_printf (header, "Host: %s:%d\r\n",
121 uri_host, uri->port);
125 if (uri_host != uri->host)
128 *encoding = soup_message_headers_get_encoding (msg->request_headers);
129 if ((*encoding == SOUP_ENCODING_CONTENT_LENGTH ||
130 *encoding == SOUP_ENCODING_NONE) &&
131 (msg->request_body->length > 0 ||
132 soup_message_headers_get_one (msg->request_headers, "Content-Type")) &&
133 !soup_message_headers_get_content_length (msg->request_headers)) {
134 *encoding = SOUP_ENCODING_CONTENT_LENGTH;
135 soup_message_headers_set_content_length (msg->request_headers,
136 msg->request_body->length);
139 soup_message_headers_iter_init (&iter, msg->request_headers);
140 while (soup_message_headers_iter_next (&iter, &name, &value))
141 g_string_append_printf (header, "%s: %s\r\n", name, value);
142 g_string_append (header, "\r\n");
146 soup_message_send_request (SoupMessageQueueItem *item,
147 SoupMessageCompletionFn completion_cb,
150 GMainContext *async_context;
153 if (!SOUP_IS_SESSION_SYNC (item->session)) {
154 async_context = soup_session_get_async_context (item->session);
156 async_context = g_main_context_default ();
158 async_context = NULL;
159 iostream = soup_socket_get_iostream (soup_connection_get_socket (item->conn));
161 soup_message_io_client (item, iostream, async_context,
163 parse_response_headers,
165 completion_cb, user_data);