4 static int port
= 8080;
5 static char *root
= NULL
;
6 static GOptionEntry cmd_entries
[] = {
7 {"port", 'p', 0, G_OPTION_ARG_INT
, &port
,
8 "Local port to bind to", NULL
},
13 send_error (GOutputStream
*out
,
19 res
= g_strdup_printf ("HTTP/1.0 %d %s\r\n\r\n"
20 "<html><head><title>%d %s</title></head>"
21 "<body>%s</body></html>",
25 g_output_stream_write_all (out
, res
, strlen (res
), NULL
, NULL
, NULL
);
30 handler (GThreadedSocketService
*service
,
31 GSocketConnection
*connection
,
32 GSocketListener
*listener
,
37 GFileInputStream
*file_in
;
38 GDataInputStream
*data
;
39 char *line
, *escaped
, *tmp
, *query
, *unescaped
, *path
, *version
;
45 in
= g_io_stream_get_input_stream (G_IO_STREAM (connection
));
46 out
= g_io_stream_get_output_stream (G_IO_STREAM (connection
));
48 data
= g_data_input_stream_new (in
);
49 /* Be tolerant of input */
50 g_data_input_stream_set_newline_type (data
, G_DATA_STREAM_NEWLINE_TYPE_ANY
);
52 line
= g_data_input_stream_read_line (data
, NULL
, NULL
, NULL
);
56 send_error (out
, 400, "Invalid request");
60 if (!g_str_has_prefix (line
, "GET "))
62 send_error (out
, 501, "Only GET implemented");
66 escaped
= line
+ 4; /* Skip "GET " */
69 tmp
= strchr (escaped
, ' ');
75 version
= version
; /* To avoid -Wunused-but-set-variable */
77 query
= strchr (escaped
, '?');
81 unescaped
= g_uri_unescape_string (escaped
, NULL
);
82 path
= g_build_filename (root
, unescaped
, NULL
);
84 f
= g_file_new_for_path (path
);
88 file_in
= g_file_read (f
, NULL
, &error
);
91 send_error (out
, 404, error
->message
);
96 s
= g_string_new ("HTTP/1.0 200 OK\r\n");
97 info
= g_file_input_stream_query_info (file_in
,
98 G_FILE_ATTRIBUTE_STANDARD_SIZE
","
99 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
103 const char *content_type
;
106 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
))
107 g_string_append_printf (s
, "Content-Length: %"G_GINT64_FORMAT
"\r\n",
108 g_file_info_get_size (info
));
109 content_type
= g_file_info_get_content_type (info
);
112 mime_type
= g_content_type_get_mime_type (content_type
);
115 g_string_append_printf (s
, "Content-Type: %s\r\n",
121 g_string_append (s
, "\r\n");
123 if (g_output_stream_write_all (out
,
127 g_output_stream_splice (out
,
128 G_INPUT_STREAM (file_in
),
131 g_string_free (s
, TRUE
);
133 g_input_stream_close (G_INPUT_STREAM (file_in
), NULL
, NULL
);
134 g_object_unref (file_in
);
137 g_object_unref (data
);
143 main (int argc
, char *argv
[])
145 GSocketService
*service
;
146 GOptionContext
*context
;
147 GError
*error
= NULL
;
149 context
= g_option_context_new ("<http root dir> - Simple HTTP server");
150 g_option_context_add_main_entries (context
, cmd_entries
, NULL
);
151 if (!g_option_context_parse (context
, &argc
, &argv
, &error
))
153 g_printerr ("%s: %s\n", argv
[0], error
->message
);
159 g_printerr ("Root directory not specified\n");
163 root
= g_strdup (argv
[1]);
165 service
= g_threaded_socket_service_new (10);
166 if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service
),
171 g_printerr ("%s: %s\n", argv
[0], error
->message
);
175 g_print ("Http server listening on port %d\n", port
);
177 g_signal_connect (service
, "run", G_CALLBACK (handler
), NULL
);
179 g_main_loop_run (g_main_loop_new (NULL
, FALSE
));
180 g_assert_not_reached ();