static gboolean mock_http_headers (CockpitWebResponse *response, GHashTable *in_headers) { GHashTableIter iter; GHashTable *headers; gpointer name, value; headers = cockpit_web_server_new_table(); g_hash_table_iter_init (&iter, in_headers); while (g_hash_table_iter_next (&iter, &name, &value)) { if (g_str_has_prefix (name, "Header")) g_hash_table_insert (headers, g_strdup (name), g_strdup (value)); } g_hash_table_replace (headers, g_strdup ("Header3"), g_strdup ("three")); g_hash_table_replace (headers, g_strdup ("Header4"), g_strdup ("marmalade")); cockpit_web_response_headers_full (response, 201, "Yoo Hoo", -1, headers); cockpit_web_response_complete (response); g_hash_table_unref (headers); return TRUE; }
static void send_login_html (CockpitWebResponse *response, CockpitHandlerData *ws) { GHashTable *headers = NULL; GList *l, *output = NULL; gchar *login_html; GMappedFile *file; GError *error = NULL; GBytes *body = NULL; gsize length; login_html = g_build_filename (ws->static_roots[0], "login.html", NULL); file = g_mapped_file_new (login_html, FALSE, &error); if (file == NULL) { g_warning ("%s: %s", login_html, error->message); cockpit_web_response_error (response, 500, NULL, NULL); g_clear_error (&error); goto out; } body = g_mapped_file_get_bytes (file); output = cockpit_template_expand (body, substitute_environment, ws->os_release); length = 0; for (l = output; l != NULL; l = g_list_next (l)) length += g_bytes_get_size (l->data); headers = cockpit_web_server_new_table (); g_hash_table_insert (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8")); cockpit_web_response_headers_full (response, 200, "OK", length, headers); for (l = output; l != NULL; l = g_list_next (l)) { if (!cockpit_web_response_queue (response, l->data)) break; } if (l == NULL) cockpit_web_response_complete (response); out: g_list_free_full (output, (GDestroyNotify)g_bytes_unref); if (headers) g_hash_table_unref (headers); g_free (login_html); if (body) g_bytes_unref (body); if (file) g_mapped_file_unref (file); }
static gboolean ensure_headers (CockpitChannelResponse *chesp, guint status, const gchar *reason) { if (cockpit_web_response_get_state (chesp->response) == COCKPIT_WEB_RESPONSE_READY) { if (chesp->inject) cockpit_channel_inject_perform (chesp->inject, chesp->response, chesp->transport); cockpit_web_response_headers_full (chesp->response, status, reason, -1, chesp->headers); return TRUE; } return FALSE; }
static gboolean mock_http_host (CockpitWebResponse *response, GHashTable *in_headers) { GHashTable *headers; headers = cockpit_web_server_new_table(); g_hash_table_insert (headers, g_strdup ("Host"), g_strdup (g_hash_table_lookup (in_headers, "Host"))); cockpit_web_response_headers_full (response, 201, "Yoo Hoo", -1, headers); cockpit_web_response_complete (response); g_hash_table_unref (headers); return TRUE; }
static void on_login_complete (GObject *object, GAsyncResult *result, gpointer user_data) { CockpitWebResponse *response = user_data; GError *error = NULL; JsonObject *response_data = NULL; GHashTable *headers; GIOStream *io_stream; GBytes *content; io_stream = cockpit_web_response_get_stream (response); headers = cockpit_web_server_new_table (); response_data = cockpit_auth_login_finish (COCKPIT_AUTH (object), result, io_stream, headers, &error); /* Never cache a login response */ cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); if (error) { if (response_data) { g_hash_table_insert (headers, g_strdup ("Content-Type"), g_strdup ("application/json")); content = cockpit_json_write_bytes (response_data); cockpit_web_response_headers_full (response, 401, "Authentication required", -1, headers); cockpit_web_response_queue (response, content); cockpit_web_response_complete (response); g_bytes_unref (content); } else { cockpit_web_response_gerror (response, headers, error); } g_error_free (error); } else { send_login_response (response, response_data, headers); } if (response_data) json_object_unref (response_data); g_hash_table_unref (headers); g_object_unref (response); }
/** * cockpit_web_response_content: * @self: the response * @headers: headers to include or NULL * @block: first block to send * * This is a simple way to send an HTTP response as a single * call. The response will be complete after this call, and will * send in the main-loop. * * The var args are additional GBytes* blocks to send, followed by * a trailing NULL. * * Don't include Content-Length or Connection in @headers. * * This calls cockpit_web_response_headers_full(), * cockpit_web_response_queue() and cockpit_web_response_complete() * internally. */ void cockpit_web_response_content (CockpitWebResponse *self, GHashTable *headers, GBytes *block, ...) { GBytes *first; gsize length = 0; va_list va; va_list va2; g_return_if_fail (COCKPIT_IS_WEB_RESPONSE (self)); first = block; va_start (va, block); va_copy (va2, va); while (block) { length += g_bytes_get_size (block); block = va_arg (va, GBytes *); } va_end (va); cockpit_web_response_headers_full (self, 200, "OK", length, headers); block = first; for (;;) { if (!block) { cockpit_web_response_complete (self); break; } if (!cockpit_web_response_queue (self, block)) break; block = va_arg (va2, GBytes *); } va_end (va2); }
/** * cockpit_web_response_error: * @self: the response * @status: the HTTP status code * @headers: headers to include or NULL * @format: printf format of error message * * Send an error message with a basic HTML page containing * the error. */ void cockpit_web_response_error (CockpitWebResponse *self, guint code, GHashTable *headers, const gchar *format, ...) { va_list var_args; gchar *reason = NULL; const gchar *message; GBytes *input = NULL; GList *output, *l; GError *error = NULL; g_return_if_fail (COCKPIT_IS_WEB_RESPONSE (self)); if (format) { va_start (var_args, format); reason = g_strdup_vprintf (format, var_args); va_end (var_args); message = reason; } else { switch (code) { case 400: message = "Bad request"; break; case 401: message = "Not Authorized"; break; case 403: message = "Forbidden"; break; case 404: message = "Not Found"; break; case 405: message = "Method Not Allowed"; break; case 413: message = "Request Entity Too Large"; break; case 502: message = "Remote Page is Unavailable"; break; case 500: message = "Internal Server Error"; break; default: if (code < 100) reason = g_strdup_printf ("%u Continue", code); else if (code < 200) reason = g_strdup_printf ("%u OK", code); else if (code < 300) reason = g_strdup_printf ("%u Moved", code); else reason = g_strdup_printf ("%u Failed", code); message = reason; break; } } g_debug ("%s: returning error: %u %s", self->logname, code, message); if (cockpit_web_failure_resource) { input = g_resources_lookup_data (cockpit_web_failure_resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error); if (input == NULL) { g_critical ("couldn't load: %s: %s", cockpit_web_failure_resource, error->message); g_error_free (error); } } if (!input) input = g_bytes_new_static (default_failure_template, strlen (default_failure_template)); if (headers) { if (!g_hash_table_lookup (headers, "Content-Type")) g_hash_table_replace (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8")); cockpit_web_response_headers_full (self, code, message, -1, headers); } else { cockpit_web_response_headers (self, code, message, -1, "Content-Type", "text/html; charset=utf8", NULL); } output = cockpit_template_expand (input, substitute_message, (gpointer)message); g_bytes_unref (input); for (l = output; l != NULL; l = g_list_next (l)) { if (!cockpit_web_response_queue (self, l->data)) break; } if (l == NULL) cockpit_web_response_complete (self); g_list_free_full (output, (GDestroyNotify)g_bytes_unref); g_free (reason); }
/** * cockpit_web_response_error: * @self: the response * @status: the HTTP status code * @headers: headers to include or NULL * @format: printf format of error message * * Send an error message with a basic HTML page containing * the error. */ void cockpit_web_response_error (CockpitWebResponse *self, guint code, GHashTable *headers, const gchar *format, ...) { gchar *body = NULL; va_list var_args; gchar *reason = NULL; const gchar *message; GBytes *content; gsize length; if (format) { va_start (var_args, format); reason = g_strdup_vprintf (format, var_args); va_end (var_args); message = reason; } else { switch (code) { case 400: message = "Bad request"; break; case 401: message = "Not Authorized"; break; case 403: message = "Forbidden"; break; case 404: message = "Not Found"; break; case 405: message = "Method Not Allowed"; break; case 413: message = "Request Entity Too Large"; break; case 500: message = "Internal Server Error"; break; default: if (code < 100) reason = g_strdup_printf ("%u Continue", code); else if (code < 200) reason = g_strdup_printf ("%u OK", code); else if (code < 300) reason = g_strdup_printf ("%u Moved", code); else reason = g_strdup_printf ("%u Failed", code); message = reason; break; } } body = g_strdup_printf ("<html><head><title>%u %s</title></head>" "<body>%s</body></html>", code, message, message); g_debug ("%s: returning error: %u %s", self->logname, code, message); length = strlen (body); content = g_bytes_new_take (body, length); cockpit_web_response_headers_full (self, code, message, length, headers); if (cockpit_web_response_queue (self, content)) cockpit_web_response_complete (self); g_bytes_unref (content); g_free (reason); }