source: trunk/third/libsoup/libsoup/soup-message-server-io.c @ 21108

Revision 21108, 4.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21107, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * soup-message-server-io.c: server-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 <stdlib.h>
13#include <string.h>
14
15#include "soup-message-private.h"
16#include "soup-address.h"
17#include "soup-auth.h"
18#include "soup-headers.h"
19#include "soup-server-message.h"
20#include "soup-server.h"
21#include "soup-socket.h"
22
23static guint
24parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
25                       SoupTransferEncoding *encoding, guint *content_len,
26                       gpointer sock)
27{
28        SoupUri *uri;
29        char *req_path = NULL, *url;
30        const char *expect, *length, *enc, *req_host;
31        SoupServer *server;
32
33        if (!soup_headers_parse_request (headers, headers_len,
34                                         msg->request_headers,
35                                         (char **) &msg->method,
36                                         &req_path,
37                                         &msg->priv->http_version))
38                return SOUP_STATUS_BAD_REQUEST;
39
40        expect = soup_message_get_header (msg->request_headers, "Expect");
41        if (expect && !strcmp (expect, "100-continue"))
42                msg->priv->msg_flags |= SOUP_MESSAGE_EXPECT_CONTINUE;
43
44        /* Handle request body encoding */
45        length = soup_message_get_header (msg->request_headers,
46                                          "Content-Length");
47        enc = soup_message_get_header (msg->request_headers,
48                                       "Transfer-Encoding");
49
50        if (enc) {
51                if (g_strcasecmp (enc, "chunked") == 0)
52                        *encoding = SOUP_TRANSFER_CHUNKED;
53                else {
54                        g_warning ("Unknown encoding type in HTTP request.");
55                        g_free (req_path);
56                        return SOUP_STATUS_NOT_IMPLEMENTED;
57                }
58        } else if (length) {
59                int len;
60                *encoding = SOUP_TRANSFER_CONTENT_LENGTH;
61                len = atoi (length);
62                if (len < 0) {
63                        g_free (req_path);
64                        return SOUP_STATUS_BAD_REQUEST;
65                }
66                *content_len = len;
67        } else {
68                *encoding = SOUP_TRANSFER_CONTENT_LENGTH;
69                *content_len = 0;
70        }
71
72        /* Generate correct context for request */
73        server = soup_server_message_get_server (SOUP_SERVER_MESSAGE (msg));
74        req_host = soup_message_get_header (msg->request_headers, "Host");
75
76        if (*req_path != '/') {
77                /* Check for absolute URI */
78                SoupUri *absolute;
79
80                absolute = soup_uri_new (req_path);
81                if (absolute) {
82                        url = g_strdup (req_path);
83                        soup_uri_free (absolute);
84                } else {
85                        g_free (req_path);
86                        return SOUP_STATUS_BAD_REQUEST;
87                }
88        } else if (req_host) {
89                url = g_strdup_printf ("%s://%s:%d%s",
90                                       soup_server_get_protocol (server) == SOUP_PROTOCOL_HTTPS ? "https" : "http",
91                                       req_host, soup_server_get_port (server),
92                                       req_path);
93        } else if (msg->priv->http_version == SOUP_HTTP_1_0) {
94                /* No Host header, no AbsoluteUri */
95                SoupAddress *addr = soup_socket_get_local_address (sock);
96                const char *host = soup_address_get_physical (addr);
97
98                url = g_strdup_printf ("%s://%s:%d%s",
99                                       soup_server_get_protocol (server) == SOUP_PROTOCOL_HTTPS ? "https" : "http",
100                                       host, soup_server_get_port (server),
101                                       req_path);
102        } else {
103                g_free (req_path);
104                return SOUP_STATUS_BAD_REQUEST;
105        }
106
107        uri = soup_uri_new (url);
108        g_free (url);
109        g_free (req_path);
110
111        if (!uri)
112                return SOUP_STATUS_BAD_REQUEST;
113
114        soup_message_set_uri (msg, uri);
115        soup_uri_free (uri);
116
117        return SOUP_STATUS_OK;
118}
119
120static void
121write_header (gpointer name, gpointer value, gpointer headers)
122{
123        g_string_append_printf (headers, "%s: %s\r\n",
124                                (char *)name, (char *)value);
125}
126
127static void
128get_response_headers (SoupMessage *msg, GString *headers,
129                      SoupTransferEncoding *encoding,
130                      gpointer user_data)
131{
132        SoupServerMessage *smsg = SOUP_SERVER_MESSAGE (msg);
133
134        g_string_append_printf (headers, "HTTP/1.1 %d %s\r\n",
135                                msg->status_code, msg->reason_phrase);
136
137        soup_message_foreach_header (msg->response_headers,
138                                     write_header, headers);
139
140        *encoding = soup_server_message_get_encoding (smsg);
141        if (*encoding == SOUP_TRANSFER_CONTENT_LENGTH) {
142                g_string_append_printf (headers, "Content-Length: %d\r\n",
143                                        msg->response.length);
144        } else if (*encoding == SOUP_TRANSFER_CHUNKED)
145                g_string_append (headers, "Transfer-Encoding: chunked\r\n");
146
147        g_string_append (headers, "\r\n");
148}
149
150/**
151 * soup_message_read_request:
152 * @req: an empty #SoupServerMessage
153 * @sock: socket to receive the request on
154 *
155 * Begins the process of receiving a request from @sock into @req.
156 **/
157void
158soup_message_read_request (SoupMessage *req, SoupSocket *sock)
159{
160        soup_message_io_server (req, sock,
161                                get_response_headers,
162                                parse_request_headers,
163                                sock);
164}
Note: See TracBrowser for help on using the repository browser.