Beispiel #1
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
/**
 * 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);
}
Beispiel #7
0
/**
 * 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);
}
Beispiel #8
0
/**
 * 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);
}