SoupLoggerPrinter printer;
gpointer printer_data;
GDestroyNotify printer_dnotify;
- char direction;
} SoupLoggerPrivate;
#define SOUP_LOGGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_LOGGER, SoupLoggerPrivate))
static void
soup_logger_print (SoupLogger *logger, SoupLoggerLogLevel level,
- const char *format, ...)
+ char direction, const char *format, ...)
{
SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger);
va_list args;
if (end)
*end = '\0';
if (priv->printer) {
- priv->printer (logger, level, priv->direction,
+ priv->printer (logger, level, direction,
line, priv->printer_data);
} else
- printf ("%c %s\n", priv->direction, line);
+ printf ("%c %s\n", direction, line);
line = end + 1;
} while (end && *line);
}
static void
-print_header (const char *name, const char *value, gpointer logger)
+soup_logger_print_basic_auth (SoupLogger *logger, const char *value)
{
- if (!g_ascii_strcasecmp (name, "Authorization") &&
- !g_ascii_strncasecmp (value, "Basic ", 6)) {
- char *decoded, *p;
- gsize len;
-
- decoded = (char *)g_base64_decode (value + 6, &len);
- if (!decoded)
- decoded = g_strdup (value);
- p = strchr (decoded, ':');
- if (p) {
- while (++p < decoded + len)
- *p = '*';
- }
- soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS,
- "%s: Basic [%.*s]", name, len, decoded);
- g_free (decoded);
- } else {
- soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS,
- "%s: %s", name, value);
+ char *decoded, *p;
+ gsize len;
+
+ decoded = (char *)g_base64_decode (value + 6, &len);
+ if (!decoded)
+ decoded = g_strdup (value);
+ p = strchr (decoded, ':');
+ if (p) {
+ while (++p < decoded + len)
+ *p = '*';
}
+ soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>',
+ "Authorization: Basic [%.*s]", len, decoded);
+ g_free (decoded);
}
static void
{
SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger);
SoupLoggerLogLevel log_level;
+ SoupMessageHeadersIter iter;
+ const char *name, *value;
SoupURI *uri;
if (priv->request_filter) {
if (log_level == SOUP_LOGGER_LOG_NONE)
return;
- priv->direction = '>';
-
uri = soup_message_get_uri (msg);
if (msg->method == SOUP_METHOD_CONNECT) {
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>',
"CONNECT %s:%u HTTP/1.%d",
uri->host, uri->port,
soup_message_get_http_version (msg));
} else {
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>',
"%s %s%s%s HTTP/1.%d",
msg->method, uri->path,
uri->query ? "?" : "",
soup_message_get_http_version (msg));
}
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>',
"Soup-Debug-Timestamp: %lu",
(unsigned long)time (0));
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>',
"Soup-Debug: %s %u (%p), %s %u (%p), %s %u (%p)%s",
g_type_name_from_instance ((GTypeInstance *)session),
soup_logger_get_id (logger, session), session,
if (log_level == SOUP_LOGGER_LOG_MINIMAL)
return;
- print_header ("Host", uri->host, logger);
- soup_message_headers_foreach (msg->request_headers,
- print_header, logger);
+ soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>',
+ "Host: %s", uri->host);
+ soup_message_headers_iter_init (&iter, msg->request_headers);
+ while (soup_message_headers_iter_next (&iter, &name, &value)) {
+ if (!g_ascii_strcasecmp (name, "Authorization") &&
+ !g_ascii_strncasecmp (value, "Basic ", 6))
+ soup_logger_print_basic_auth (logger, value);
+ else {
+ soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>',
+ "%s: %s", name, value);
+ }
+ }
if (log_level == SOUP_LOGGER_LOG_HEADERS)
return;
soup_buffer_free (request);
if (soup_message_headers_get_expectations (msg->request_headers) != SOUP_EXPECTATION_CONTINUE) {
- soup_logger_print (logger, SOUP_LOGGER_LOG_BODY,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '>',
"\n%s", msg->request_body->data);
}
}
{
SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger);
SoupLoggerLogLevel log_level;
+ SoupMessageHeadersIter iter;
+ const char *name, *value;
if (priv->response_filter) {
log_level = priv->response_filter (logger, msg,
if (log_level == SOUP_LOGGER_LOG_NONE)
return;
- priv->direction = '<';
-
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<',
"HTTP/1.%d %u %s\n",
soup_message_get_http_version (msg),
msg->status_code, msg->reason_phrase);
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<',
"Soup-Debug-Timestamp: %lu",
(unsigned long)time (0));
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<',
"Soup-Debug: %s %u (%p)",
g_type_name_from_instance ((GTypeInstance *)msg),
soup_logger_get_id (logger, msg), msg);
if (log_level == SOUP_LOGGER_LOG_MINIMAL)
return;
- soup_message_headers_foreach (msg->response_headers,
- print_header, logger);
+ soup_message_headers_iter_init (&iter, msg->response_headers);
+ while (soup_message_headers_iter_next (&iter, &name, &value)) {
+ soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '<',
+ "%s: %s", name, value);
+ }
if (log_level == SOUP_LOGGER_LOG_HEADERS)
return;
if (msg->response_body->length) {
- soup_logger_print (logger, SOUP_LOGGER_LOG_BODY,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '<',
"\n%s", msg->response_body->data);
}
}
g_mutex_lock (priv->lock);
print_response (logger, msg);
- priv->direction = ' ';
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, "");
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "");
if (msg->status_code == SOUP_STATUS_CONTINUE && msg->request_body->data) {
SoupLoggerLogLevel log_level;
- priv->direction = '>';
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>',
"[Now sending request body...]");
if (priv->request_filter) {
log_level = priv->level;
if (log_level == SOUP_LOGGER_LOG_BODY) {
- soup_logger_print (logger, SOUP_LOGGER_LOG_BODY,
+ soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '>',
"%s", msg->request_body->data);
}
- priv->direction = ' ';
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, "");
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "");
}
g_mutex_unlock (priv->lock);
g_mutex_lock (priv->lock);
print_response (logger, msg);
- priv->direction = ' ';
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, "");
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "");
g_mutex_unlock (priv->lock);
}
SoupSocket *socket, gpointer user_data)
{
SoupLogger *logger = user_data;
- SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger);
gboolean restarted;
guint msg_id;
soup_logger_set_id (logger, socket);
print_request (logger, msg, session, socket, restarted);
- priv->direction = ' ';
- soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, "");
+ soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "");
}
}
/**
+ * SoupMessageHeadersIter:
+ *
+ * An opaque type used to iterate over a %SoupMessageHeaders
+ * structure.
+ *
+ * After intializing the iterator with
+ * soup_message_headers_iter_init(), call
+ * soup_message_headers_iter_next() to fetch data from it.
+ *
+ * You may not modify the headers while iterating over them.
+ **/
+
+typedef struct {
+ SoupMessageHeaders *hdrs;
+ int index;
+} SoupMessageHeadersIterReal;
+
+/**
+ * soup_message_headers_iter_init:
+ * @iter: a pointer to a %SoupMessageHeadersIter structure
+ * @hdrs: a %SoupMessageHeaders
+ *
+ * Initializes @iter for iterating @hdrs.
+ **/
+void
+soup_message_headers_iter_init (SoupMessageHeadersIter *iter,
+ SoupMessageHeaders *hdrs)
+{
+ SoupMessageHeadersIterReal *real = (SoupMessageHeadersIterReal *)iter;
+
+ real->hdrs = hdrs;
+ real->index = 0;
+}
+
+/**
+ * soup_message_headers_iter_next:
+ * @iter: a %SoupMessageHeadersIter
+ * @name: pointer to a variable to return the header name in
+ * @value: pointer to a variable to return the header value in
+ *
+ * Yields the next name/value pair in the %SoupMessageHeaders being
+ * iterated by @iter. If @iter has already yielded the last header,
+ * then soup_message_headers_iter_next() will return %FALSE and @name
+ * and @value will be unchanged.
+ *
+ * Return value: %TRUE if another name and value were returned, %FALSE
+ * if the end of the headers has been reached.
+ **/
+gboolean
+soup_message_headers_iter_next (SoupMessageHeadersIter *iter,
+ const char **name, const char **value)
+{
+ SoupMessageHeadersIterReal *real = (SoupMessageHeadersIterReal *)iter;
+ SoupHeader *hdr_array = (SoupHeader *)real->hdrs->array->data;
+
+ if (real->index >= real->hdrs->array->len)
+ return FALSE;
+
+ *name = hdr_array[real->index].name;
+ *value = hdr_array[real->index].value;
+ real->index++;
+ return TRUE;
+}
+
+/**
* SoupMessageHeadersForeachFunc:
* @name: the header name
* @value: the header value
* then the I/O code will output multiple copies of the header when
* sending the message to the remote implementation, which may be
* required for interoperability in some cases.)
+ *
+ * You may not modify the headers from @func.
**/
void
soup_message_headers_foreach (SoupMessageHeaders *hdrs,