source: trunk/third/libsoup/tests/simple-httpd.c @ 21108

Revision 21108, 4.6 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 * Copyright (C) 2001-2003, Ximian, Inc.
4 */
5
6#include <ctype.h>
7#include <fcntl.h>
8#include <errno.h>
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16#include <glib.h>
17#include <libsoup/soup-address.h>
18#include <libsoup/soup-message.h>
19#include <libsoup/soup-server.h>
20#include <libsoup/soup-server-message.h>
21
22static void
23print_header (gpointer name, gpointer value, gpointer data)
24{
25        printf ("%s: %s\n", (char *)name, (char *)value);
26}
27
28static void
29server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
30{
31        char *path, *path_to_open, *slash;
32        struct stat st;
33        int fd;
34
35        path = soup_uri_to_string (soup_message_get_uri (msg), TRUE);
36        printf ("%s %s HTTP/1.%d\n", msg->method, path,
37                soup_message_get_http_version (msg));
38        soup_message_foreach_header (msg->request_headers, print_header, NULL);
39        if (msg->request.length)
40                printf ("%.*s\n", msg->request.length, msg->request.body);
41
42        if (soup_method_get_id (msg->method) != SOUP_METHOD_ID_GET) {
43                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
44                goto DONE;
45        }
46
47        if (path) {
48                if (*path != '/') {
49                        soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
50                        goto DONE;
51                }
52        } else
53                path = g_strdup ("");
54
55        path_to_open = g_strdup_printf (".%s", path);
56
57 TRY_AGAIN:
58        if (stat (path_to_open, &st) == -1) {
59                g_free (path_to_open);
60                if (errno == EPERM)
61                        soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
62                else if (errno == ENOENT)
63                        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
64                else
65                        soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
66                goto DONE;
67        }
68
69        if (S_ISDIR (st.st_mode)) {
70                slash = strrchr (path_to_open, '/');
71                if (!slash || slash[1]) {
72                        char *uri, *redir_uri;
73
74                        uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
75                        redir_uri = g_strdup_printf ("%s/", uri);
76                        soup_message_add_header (msg->response_headers,
77                                                 "Location", redir_uri);
78                        soup_message_set_status (msg, SOUP_STATUS_MOVED_PERMANENTLY);
79                        g_free (redir_uri);
80                        g_free (uri);
81                        g_free (path_to_open);
82                        goto DONE;
83                }
84
85                g_free (path_to_open);
86                path_to_open = g_strdup_printf (".%s/index.html", path);
87                goto TRY_AGAIN;
88        }
89
90        fd = open (path_to_open, O_RDONLY);
91        g_free (path_to_open);
92        if (fd == -1) {
93                soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
94                goto DONE;
95        }
96
97        msg->response.owner = SOUP_BUFFER_SYSTEM_OWNED;
98        msg->response.length = st.st_size;
99        msg->response.body = g_malloc (msg->response.length);
100
101        read (fd, msg->response.body, msg->response.length);
102        close (fd);
103
104        soup_message_set_status (msg, SOUP_STATUS_OK);
105
106 DONE:
107        g_free (path);
108        soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg),
109                                          SOUP_TRANSFER_CONTENT_LENGTH);
110        printf ("  -> %d %s\n\n", msg->status_code, msg->reason_phrase);
111}
112
113static void
114quit (int sig)
115{
116        /* Exit cleanly on ^C in case we're valgrinding. */
117        exit (0);
118}
119
120int
121main (int argc, char **argv)
122{
123        GMainLoop *loop;
124        SoupServer *server, *ssl_server;
125        int opt;
126        int port = SOUP_ADDRESS_ANY_PORT;
127        int ssl_port = SOUP_ADDRESS_ANY_PORT;
128        const char *ssl_cert_file = NULL, *ssl_key_file = NULL;
129
130        g_type_init ();
131        g_thread_init (NULL);
132        signal (SIGINT, quit);
133
134        while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) {
135                switch (opt) {
136                case 'p':
137                        port = atoi (optarg);
138                        break;
139                case 'k':
140                        ssl_key_file = optarg;
141                        break;
142                case 'c':
143                        ssl_cert_file = optarg;
144                        break;
145                case 's':
146                        ssl_port = atoi (optarg);
147                        break;
148                default:
149                        fprintf (stderr, "Usage: %s [-p port] [-c ssl-cert-file -k ssl-key-file [-s ssl-port]]\n",
150                                 argv[0]);
151                        exit (1);
152                }
153        }
154
155        server = soup_server_new (SOUP_SERVER_PORT, port,
156                                  NULL);
157        if (!server) {
158                fprintf (stderr, "Unable to bind to server port %d\n", port);
159                exit (1);
160        }
161        soup_server_add_handler (server, NULL, NULL,
162                                 server_callback, NULL, NULL);
163        printf ("\nStarting Server on port %d\n",
164                soup_server_get_port (server));
165        soup_server_run_async (server);
166
167        if (ssl_cert_file && ssl_key_file) {
168                ssl_server = soup_server_new (
169                        SOUP_SERVER_PORT, ssl_port,
170                        SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file,
171                        SOUP_SERVER_SSL_KEY_FILE, ssl_key_file,
172                        NULL);
173
174                if (!ssl_server) {
175                        fprintf (stderr, "Unable to bind to SSL server port %d\n", ssl_port);
176                        exit (1);
177                }
178                soup_server_add_handler (ssl_server, NULL, NULL,
179                                         server_callback, NULL, NULL);
180                printf ("Starting SSL Server on port %d\n",
181                        soup_server_get_port (ssl_server));
182                soup_server_run_async (ssl_server);
183        }
184
185        printf ("\nWaiting for requests...\n");
186
187        loop = g_main_loop_new (NULL, TRUE);
188        g_main_loop_run (loop);
189
190        return 0;
191}
Note: See TracBrowser for help on using the repository browser.