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.
15 #include "soup-connection.h"
16 #include "soup-message-private.h"
17 #include "soup-auth.h"
18 #include "soup-connection.h"
19 #include "soup-headers.h"
20 #include "soup-message-queue.h"
24 parse_response_headers (SoupMessage *req,
25 char *headers, guint headers_len,
26 SoupEncoding *encoding,
29 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
30 SoupHTTPVersion version;
32 g_free(req->reason_phrase);
33 req->reason_phrase = NULL;
34 if (!soup_headers_parse_response (headers, headers_len,
35 req->response_headers,
39 return SOUP_STATUS_MALFORMED;
41 g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE);
42 g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE);
44 if (version < priv->http_version) {
45 priv->http_version = version;
46 g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION);
49 if ((req->method == SOUP_METHOD_HEAD ||
50 req->status_code == SOUP_STATUS_NO_CONTENT ||
51 req->status_code == SOUP_STATUS_NOT_MODIFIED ||
52 SOUP_STATUS_IS_INFORMATIONAL (req->status_code)) ||
53 (req->method == SOUP_METHOD_CONNECT &&
54 SOUP_STATUS_IS_SUCCESSFUL (req->status_code)))
55 *encoding = SOUP_ENCODING_NONE;
57 *encoding = soup_message_headers_get_encoding (req->response_headers);
59 if (*encoding == SOUP_ENCODING_UNRECOGNIZED)
60 return SOUP_STATUS_MALFORMED;
62 return SOUP_STATUS_OK;
66 get_request_headers (SoupMessage *req, GString *header,
67 SoupEncoding *encoding, gpointer user_data)
69 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
70 SoupMessageQueueItem *item = user_data;
71 SoupURI *uri = soup_message_get_uri (req);
74 SoupMessageHeadersIter iter;
75 const char *name, *value;
77 if (strchr (uri->host, ':'))
78 uri_host = g_strdup_printf ("[%s]", uri->host);
79 else if (g_hostname_is_non_ascii (uri->host))
80 uri_host = g_hostname_to_ascii (uri->host);
84 if (req->method == SOUP_METHOD_CONNECT) {
85 /* CONNECT URI is hostname:port for tunnel destination */
86 uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port);
88 gboolean proxy = soup_connection_is_via_proxy (item->conn);
90 /* Proxy expects full URI to destination. Otherwise
93 uri_string = soup_uri_to_string (uri, !proxy);
95 if (proxy && uri->fragment) {
97 char *fragment = strchr (uri_string, '#');
103 if (priv->http_version == SOUP_HTTP_1_0) {
104 g_string_append_printf (header, "%s %s HTTP/1.0\r\n",
105 req->method, uri_string);
107 g_string_append_printf (header, "%s %s HTTP/1.1\r\n",
108 req->method, uri_string);
109 if (!soup_message_headers_get_one (req->request_headers, "Host")) {
110 if (soup_uri_uses_default_port (uri)) {
111 g_string_append_printf (header, "Host: %s\r\n",
114 g_string_append_printf (header, "Host: %s:%d\r\n",
115 uri_host, uri->port);
120 if (uri_host != uri->host)
123 *encoding = soup_message_headers_get_encoding (req->request_headers);
124 if ((*encoding == SOUP_ENCODING_CONTENT_LENGTH ||
125 *encoding == SOUP_ENCODING_NONE) &&
126 (req->request_body->length > 0 ||
127 soup_message_headers_get_one (req->request_headers, "Content-Type")) &&
128 !soup_message_headers_get_content_length (req->request_headers)) {
129 *encoding = SOUP_ENCODING_CONTENT_LENGTH;
130 soup_message_headers_set_content_length (req->request_headers,
131 req->request_body->length);
134 soup_message_headers_iter_init (&iter, req->request_headers);
135 while (soup_message_headers_iter_next (&iter, &name, &value))
136 g_string_append_printf (header, "%s: %s\r\n", name, value);
137 g_string_append (header, "\r\n");
141 soup_message_send_request (SoupMessageQueueItem *item,
142 SoupMessageCompletionFn completion_cb,
145 soup_message_cleanup_response (item->msg);
146 soup_message_io_client (item,
148 parse_response_headers,
150 completion_cb, user_data);