fixed typo enable_sqllite -> enable_sqlite
[platform/upstream/libsoup.git] / libsoup / soup-message-client-io.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-message-client-io.c: client-side request/response
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <string.h>
13
14 #include <glib/gi18n-lib.h>
15
16 #include "soup.h"
17 #include "soup-connection.h"
18 #include "soup-message-private.h"
19 #include "soup-message-queue.h"
20 #include "soup-misc-private.h"
21
22 static guint
23 parse_response_headers (SoupMessage *msg,
24                         char *headers, guint headers_len,
25                         SoupEncoding *encoding,
26                         gpointer user_data,
27                         GError **error)
28 {
29         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
30         SoupHTTPVersion version;
31
32         g_free(msg->reason_phrase);
33         msg->reason_phrase = NULL;
34         if (!soup_headers_parse_response (headers, headers_len,
35                                           msg->response_headers,
36                                           &version,
37                                           &msg->status_code,
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;
43         }
44
45         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
46         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
47
48         if (version < priv->http_version) {
49                 priv->http_version = version;
50                 g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION);
51         }
52
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;
60         else
61                 *encoding = soup_message_headers_get_encoding (msg->response_headers);
62
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;
68         }
69
70         return SOUP_STATUS_OK;
71 }
72
73 static void
74 get_request_headers (SoupMessage *msg, GString *header,
75                      SoupEncoding *encoding, gpointer user_data)
76 {
77         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
78         SoupMessageQueueItem *item = user_data;
79         SoupURI *uri = soup_message_get_uri (msg);
80         char *uri_host;
81         char *uri_string;
82         SoupMessageHeadersIter iter;
83         const char *name, *value;
84
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);
89         else
90                 uri_host = uri->host;
91
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);
95         } else {
96                 gboolean proxy = soup_connection_is_via_proxy (item->conn);
97
98                 /* Proxy expects full URI to destination. Otherwise
99                  * just the path.
100                  */
101                 uri_string = soup_uri_to_string (uri, !proxy);
102
103                 if (proxy && uri->fragment) {
104                         /* Strip fragment */
105                         char *fragment = strchr (uri_string, '#');
106                         if (fragment)
107                                 *fragment = '\0';
108                 }
109         }
110
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);
114
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",
118                                                 uri_host);
119                 } else {
120                         g_string_append_printf (header, "Host: %s:%d\r\n",
121                                                 uri_host, uri->port);
122                 }
123         }
124         g_free (uri_string);
125         if (uri_host != uri->host)
126                 g_free (uri_host);
127
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);
137         }
138
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");
143 }
144
145 void
146 soup_message_send_request (SoupMessageQueueItem      *item,
147                            SoupMessageCompletionFn    completion_cb,
148                            gpointer                   user_data)
149 {
150         GMainContext *async_context;
151         GIOStream *iostream;
152
153         if (!SOUP_IS_SESSION_SYNC (item->session)) {
154                 async_context = soup_session_get_async_context (item->session);
155                 if (!async_context)
156                         async_context = g_main_context_default ();
157         } else
158                 async_context = NULL;
159         iostream = soup_socket_get_iostream (soup_connection_get_socket (item->conn));
160
161         soup_message_io_client (item, iostream, async_context,
162                                 get_request_headers,
163                                 parse_response_headers,
164                                 item,
165                                 completion_cb, user_data);
166 }