session, msg, auth, retrying);
}
+/* At some point it might be possible to mark additional methods
+ * safe or idempotent...
+ */
#define SOUP_METHOD_IS_SAFE(method) (method == SOUP_METHOD_GET || \
method == SOUP_METHOD_HEAD || \
method == SOUP_METHOD_OPTIONS || \
method == SOUP_METHOD_PROPFIND)
+#define SOUP_METHOD_IS_IDEMPOTENT(method) (method == SOUP_METHOD_GET || \
+ method == SOUP_METHOD_HEAD || \
+ method == SOUP_METHOD_OPTIONS || \
+ method == SOUP_METHOD_PROPFIND || \
+ method == SOUP_METHOD_PUT || \
+ method == SOUP_METHOD_DELETE)
+
+
#define SOUP_SESSION_WOULD_REDIRECT_AS_GET(session, msg) \
((msg)->status_code == SOUP_STATUS_SEE_OTHER || \
((msg)->status_code == SOUP_STATUS_FOUND && \
GSList *conns;
int num_pending = 0;
SoupURI *uri;
+ gboolean need_new_connection;
if (item->conn) {
g_return_val_if_fail (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED, FALSE);
return TRUE;
}
+ need_new_connection =
+ (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) ||
+ !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method);
+
g_mutex_lock (&priv->host_lock);
host = get_host_for_message (session, item->msg);
for (conns = host->connections; conns; conns = conns->next) {
- if (soup_connection_get_state (conns->data) == SOUP_CONNECTION_IDLE) {
+ if (!need_new_connection && soup_connection_get_state (conns->data) == SOUP_CONNECTION_IDLE) {
soup_connection_set_state (conns->data, SOUP_CONNECTION_IN_USE);
g_mutex_unlock (&priv->host_lock);
item->conn = g_object_ref (conns->data);
}
if (host->num_conns >= priv->max_conns_per_host) {
+ if (need_new_connection)
+ *try_pruning = TRUE;
g_mutex_unlock (&priv->host_lock);
return FALSE;
}
return;
}
- if (msg->method != SOUP_METHOD_GET) {
+ if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
return;
}
}
static void
-timeout_test_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer user_data)
+request_started_socket_collector (SoupSession *session, SoupMessage *msg,
+ SoupSocket *socket, gpointer user_data)
{
SoupSocket **sockets = user_data;
int i;
int i;
g_signal_connect (session, "request-started",
- G_CALLBACK (timeout_test_request_started),
+ G_CALLBACK (request_started_socket_collector),
&sockets);
debug_printf (1, " First message\n");
soup_test_session_abort_unref (session);
}
+static void
+do_non_persistent_test_for_session (SoupSession *session)
+{
+ SoupMessage *msg;
+ SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL };
+ int i;
+
+ g_signal_connect (session, "request-started",
+ G_CALLBACK (request_started_socket_collector),
+ &sockets);
+
+ debug_printf (2, " GET\n");
+ msg = soup_message_new_from_uri ("GET", base_uri);
+ soup_session_send_message (session, msg);
+ if (msg->status_code != SOUP_STATUS_OK) {
+ debug_printf (1, " Unexpected response: %d %s\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ }
+ if (sockets[1]) {
+ debug_printf (1, " Message was retried??\n");
+ errors++;
+ sockets[1] = sockets[2] = sockets[3] = NULL;
+ }
+ g_object_unref (msg);
+
+ debug_printf (2, " POST\n");
+ msg = soup_message_new_from_uri ("POST", base_uri);
+ soup_session_send_message (session, msg);
+ if (msg->status_code != SOUP_STATUS_OK) {
+ debug_printf (1, " Unexpected response: %d %s\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ }
+ if (sockets[1] == sockets[0]) {
+ debug_printf (1, " Message was sent on existing connection!\n");
+ errors++;
+ }
+ if (sockets[2]) {
+ debug_printf (1, " Too many connections used...\n");
+ errors++;
+ }
+ g_object_unref (msg);
+
+ for (i = 0; sockets[i]; i++)
+ g_object_unref (sockets[i]);
+}
+
+static void
+do_non_persistent_connection_test (void)
+{
+ SoupSession *session;
+
+ debug_printf (1, "\nNon-idempotent methods are always sent on new connections\n");
+
+ debug_printf (1, " Async session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_non_persistent_test_for_session (session);
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " Sync session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ do_non_persistent_test_for_session (session);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
do_max_conns_test ();
do_cancel_while_reading_test ();
do_aliases_test ();
+ do_non_persistent_connection_test ();
soup_uri_free (base_uri);
soup_uri_free (ssl_base_uri);