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-session-async.h>
22 /* WARNING: this is really really really not especially compliant with
23 * RFC 2616. But it does work for basic stuff.
30 copy_header (const char *name, const char *value, gpointer dest_headers)
32 soup_message_headers_append (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_headers_foreach (from->response_headers, copy_header,
45 to->response_headers);
46 soup_message_headers_remove (to->response_headers, "Content-Length");
47 soup_server_unpause_message (server, to);
51 send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to)
53 printf ("[%p] writing chunk of %lu bytes\n", to,
54 (unsigned long)chunk->length);
56 soup_message_body_append_buffer (to->response_body, chunk);
57 soup_server_unpause_message (server, to);
61 client_msg_failed (SoupMessage *msg, gpointer msg2)
63 soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR);
67 finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data)
69 SoupMessage *msg = data;
71 printf ("[%p] done\n\n", msg);
72 g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2);
74 soup_message_body_complete (msg->response_body);
75 soup_server_unpause_message (server, msg);
80 server_callback (SoupServer *server, SoupMessage *msg,
81 const char *path, GHashTable *query,
82 SoupClientContext *context, gpointer data)
87 uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
88 printf ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
89 soup_message_get_http_version (msg));
91 if (msg->method == SOUP_METHOD_CONNECT) {
92 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
96 msg2 = soup_message_new (msg->method, uristr);
97 msg2 = soup_message_new (msg->method, uristr);
98 soup_message_headers_foreach (msg->request_headers, copy_header,
99 msg2->request_headers);
100 soup_message_headers_remove (msg2->request_headers, "Host");
101 soup_message_headers_remove (msg2->request_headers, "Connection");
103 if (msg->request_body->length) {
104 SoupBuffer *request = soup_message_body_flatten (msg->request_body);
105 soup_message_body_append_buffer (msg2->request_body, request);
106 soup_buffer_free (request);
108 soup_message_headers_set_encoding (msg->response_headers,
109 SOUP_ENCODING_CHUNKED);
111 g_signal_connect (msg2, "got_headers",
112 G_CALLBACK (send_headers), msg);
113 g_signal_connect (msg2, "got_chunk",
114 G_CALLBACK (send_chunk), msg);
116 g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);
118 soup_session_queue_message (session, msg2, finish_msg, msg);
121 soup_server_pause_message (server, msg);
127 /* Exit cleanly on ^C in case we're valgrinding. */
132 main (int argc, char **argv)
136 int port = SOUP_ADDRESS_ANY_PORT;
138 g_thread_init (NULL);
140 signal (SIGINT, quit);
142 while ((opt = getopt (argc, argv, "p:s:")) != -1) {
145 port = atoi (optarg);
148 fprintf (stderr, "Usage: %s [-p port] [-n]\n",
154 server = soup_server_new (SOUP_SERVER_PORT, port,
157 fprintf (stderr, "Unable to bind to server port %d\n", port);
160 soup_server_add_handler (server, NULL,
161 server_callback, NULL, NULL);
163 printf ("\nStarting proxy on port %d\n",
164 soup_server_get_port (server));
165 soup_server_run_async (server);
167 session = soup_session_async_new ();
169 printf ("\nWaiting for requests...\n");
171 loop = g_main_loop_new (NULL, TRUE);
172 g_main_loop_run (loop);
173 g_main_loop_unref (loop);