1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003, Ximian, Inc.
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 #include <libsoup/soup-session.h>
23 /* WARNING: this is really really really not especially compliant with
24 * RFC 2616. But it does work for basic stuff.
30 copy_header (gpointer name, gpointer value, gpointer dest_headers)
32 soup_message_add_header (dest_headers, name, value);
36 send_headers (SoupMessage *from, SoupMessage *to)
38 printf ("[%p] HTTP/1.%d %d %s\n", to,
39 soup_message_get_http_version (from),
40 from->status_code, from->reason_phrase);
42 soup_message_set_status_full (to, from->status_code,
44 soup_message_foreach_header (from->response_headers, copy_header,
45 to->response_headers);
46 soup_message_remove_header (to->response_headers, "Content-Length");
47 soup_message_io_unpause (to);
51 send_chunk (SoupMessage *from, SoupMessage *to)
53 printf ("[%p] writing chunk of %d bytes\n", to, from->response.length);
55 soup_message_add_chunk (to, SOUP_BUFFER_USER_OWNED,
56 from->response.body, from->response.length);
57 soup_message_io_unpause (to);
61 client_msg_failed (SoupMessage *msg, gpointer msg2)
63 soup_message_cancel (msg2);
67 finish_msg (SoupMessage *msg2, gpointer msg)
69 printf ("[%p] done\n\n", msg);
70 g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2);
72 soup_message_add_final_chunk (msg);
73 soup_message_io_unpause (msg);
78 server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
83 uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
84 printf ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
85 soup_message_get_http_version (msg));
87 if (soup_method_get_id (msg->method) == SOUP_METHOD_ID_CONNECT) {
88 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
92 msg2 = soup_message_new (msg->method, uristr);
93 soup_message_foreach_header (msg->request_headers, copy_header,
94 msg2->request_headers);
95 soup_message_remove_header (msg2->request_headers, "Host");
96 soup_message_remove_header (msg2->request_headers, "Connection");
98 if (msg->request.length) {
99 msg2->request.owner = SOUP_BUFFER_USER_OWNED;
100 msg2->request.body = msg->request.body;
101 msg2->request.length = msg->request.length;
103 soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg),
104 SOUP_TRANSFER_CHUNKED);
106 g_signal_connect (msg2, "got_headers",
107 G_CALLBACK (send_headers), msg);
108 g_signal_connect (msg2, "got_chunk",
109 G_CALLBACK (send_chunk), msg);
110 soup_message_set_flags (msg2, SOUP_MESSAGE_OVERWRITE_CHUNKS);
112 g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);
114 soup_session_queue_message (session, msg2, finish_msg, msg);
117 soup_message_io_pause (msg);
123 /* Exit cleanly on ^C in case we're valgrinding. */
128 main (int argc, char **argv)
132 int port = SOUP_ADDRESS_ANY_PORT;
136 signal (SIGINT, quit);
138 while ((opt = getopt (argc, argv, "p:s:")) != -1) {
141 port = atoi (optarg);
144 fprintf (stderr, "Usage: %s [-p port] [-n]\n",
150 server = soup_server_new (SOUP_PROTOCOL_HTTP, port);
152 fprintf (stderr, "Unable to bind to server port %d\n", port);
155 soup_server_add_handler (server, NULL, NULL,
156 server_callback, NULL, NULL);
158 printf ("\nStarting proxy on port %d\n",
159 soup_server_get_port (server));
160 soup_server_run_async (server);
162 session = soup_session_new_default ();
164 printf ("\nWaiting for requests...\n");
166 loop = g_main_loop_new (NULL, TRUE);
167 g_main_loop_run (loop);
168 g_main_loop_unref (loop);