26#include <glib/gi18n.h>
29#include <libsoup/soup.h>
32#ifndef LIBSOUP_VERSION_MAJOR
33#error "LIBSOUP_VERSION_MAJOR not defined by CMake"
35#if LIBSOUP_VERSION_MAJOR >= 3
53 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
57 " background-color: #575656;\n"
58 " font-family: \"Lucida Grande\",Verdana,\"Bitstream Vera Sans\",Arial,sans-serif;\n"
60 " padding: 50px 100px 50px 100px;\n"
63 " background-color: #cfcece;\n"
64 " border: 1px solid #000;\n"
65 " padding: 0px 40px 40px 40px;\n"
69 " if(window.location.hash && %d) {\n"
70 " var hash = window.location.hash.substring(1);\n"
71 " window.location.search = hash;\n"
75 "<body><div id=\"content\">\n"
76 "<div style=\"font-size: 42pt; font-weight: bold; color: white; text-align: right;\">%s</div>\n"
84static gboolean _delayed_kill(gpointer user_data)
87 return G_SOURCE_REMOVE;
99static void _new_connection(SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
100 SoupClientContext *client, gpointer user_data)
105 if(msg->method != SOUP_METHOD_GET)
107 soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
111 char *page_title = g_strdup_printf(_(
"ansel >> %s"), params->id);
112 const char *title = _(params->id);
113 const char *body = _(
"<h1>Sorry,</h1><p>something went wrong. Please try again.</p>");
115 res = params->callback(query, params->user_data);
118 body = _(
"<h1>Thank you,</h1><p>everything should have worked, you can <b>close</b> your browser now and "
119 "<b>go back</b> to Ansel.</p>");
121 char *resp_body = g_strdup_printf(
reply, page_title, res ? 0 : 1, title, body);
122 size_t resp_length = strlen(resp_body);
125 soup_message_set_status(msg, SOUP_STATUS_OK);
126 soup_message_set_response(msg,
"text/html", SOUP_MEMORY_TAKE, resp_body, resp_length);
132 soup_server_remove_handler(server, path);
140static void _new_connection(SoupServer *server, SoupServerMessage *msg, gpointer user_data)
144 if(g_strcmp0(soup_server_message_get_method(msg), SOUP_METHOD_GET) != 0)
146 soup_server_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED,
"Not Implemented");
152 gboolean res =
params->callback(query,
params->user_data);
153 g_hash_table_unref(query);
155 const char *body = res ?
156 _(
"<h1>Thank you,</h1><p>everything should have worked, you can <b>close</b> your browser now and "
157 "<b>go back</b> to Ansel.</p>") :
158 _(
"<h1>Sorry,</h1><p>something went wrong. Please try again.</p>");
160 char *page_title = g_strdup_printf(_(
"ansel >> %s"),
params->id);
161 char *resp_body = g_strdup_printf(
reply, page_title, res ? 0 : 1, _(
params->id), body);
164 soup_server_message_set_status(msg, SOUP_STATUS_OK,
"OK");
165 soup_server_message_set_response(msg,
"text/html; charset=utf-8",
166 SOUP_MEMORY_TAKE, resp_body, strlen(resp_body));
169 g_timeout_add(100, _delayed_kill,
params->server);
176 SoupServer *httpserver = NULL;
183 httpserver = soup_server_new(SOUP_SERVER_SERVER_HEADER,
"ansel internal server", NULL);
186 fprintf(stderr,
"error: couldn't create libsoup httpserver\n");
190 for(
int i = 0;
i < n_ports;
i++)
193 if(soup_server_listen_local(httpserver, port, 0, NULL))
break;
198 g_object_unref(httpserver);
199 fprintf(stderr,
"error: can't bind to any port from our pool\n");
205#elif defined(LIBSOUP3)
207SoupServerListener *listener = soup_server_get_listener(httpserver);
209 GMainContext *ctx = g_main_context_default();
210 soup_server_listener_set_context(listener, ctx);
212soup_server_run(httpserver);
215#elif defined(LIBSOUP3)
219 httpserver = soup_server_new(
"server-header",
"ansel internal server", NULL);
222 fprintf(stderr,
"error: couldn't create libsoup httpserver\n");
226 for(
int i = 0;
i < n_ports;
i++)
229 if(soup_server_listen_local(httpserver, port, SOUP_SERVER_LISTEN_IPV4_ONLY, NULL))
break;
234 g_object_unref(httpserver);
235 fprintf(stderr,
"error: can't bind to any port from our pool\n");
241 server->
server = httpserver;
245 params->server = server;
246 params->callback = callback;
247 params->user_data = user_data;
249 char *path = g_strdup_printf(
"/%s",
id);
250 server->
url = g_strdup_printf(
"http://localhost:%d%s", port, path);
253 soup_server_add_handler(httpserver, path,
_new_connection, params, (GDestroyNotify)free);
255 soup_server_add_early_handler(httpserver, path, (SoupServerCallback)
_new_connection, params, (GDestroyNotify)g_free);
266 if(server && server->
server)
268 soup_server_disconnect(server->
server);
269 g_object_unref(server->
server);
void dt_print(dt_debug_thread_t thread, const char *msg,...)
static void dt_free_gpointer(gpointer ptr)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
void dt_http_server_kill(dt_http_server_t *server)
static void _request_finished_callback(SoupServer *server, SoupMessage *message, SoupClientContext *client, gpointer user_data)
static void _new_connection(SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client, gpointer user_data)
static const char reply[]
dt_http_server_t * dt_http_server_create(const int *ports, const int n_ports, const char *id, const dt_http_server_callback callback, gpointer user_data)
gboolean(* dt_http_server_callback)(GHashTable *query, gpointer user_data)
dt_http_server_callback callback
dt_http_server_t * server