[libgdata/libgdata-0-6] [core] Improve error reporting when there's no network connection



commit 73920df8d9751b583dbc15ca5aee125de3808703
Author: Philip Withnall <philip tecnocode co uk>
Date:   Mon Mar 29 19:19:45 2010 +0100

    [core] Improve error reporting when there's no network connection
    
    Add GDATA_SERVICE_ERROR_NETWORK_ERROR and GDATA_SERVICE_ERROR_PROXY_ERROR,
    to be returned by all network operations (authentication, queries,
    insertions, updates and	deletions) in case of a	local network error or a
    proxy error, respectively.

 gdata/gdata-service.c |   37 ++++++++++++++++++++++++++++---------
 gdata/gdata-service.h |   12 +++++++++---
 gdata/tests/general.c |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 12 deletions(-)
---
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index e331e98..8279d53 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -334,29 +334,42 @@ real_parse_error_response (GDataService *self, GDataOperationType operation_type
 {
 	/* See: http://code.google.com/apis/gdata/docs/2.0/reference.html#HTTPStatusCodes */
 	switch (status) {
-		case 400:
+		case SOUP_STATUS_CANT_RESOLVE:
+		case SOUP_STATUS_CANT_CONNECT:
+		case SOUP_STATUS_SSL_FAILED:
+		case SOUP_STATUS_IO_ERROR:
+			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NETWORK_ERROR,
+			             _("Cannot connect to the service's server."));
+			return;
+		case SOUP_STATUS_CANT_RESOLVE_PROXY:
+		case SOUP_STATUS_CANT_CONNECT_PROXY:
+			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROXY_ERROR,
+			             _("Cannot connect to the proxy server."));
+			return;
+		case SOUP_STATUS_MALFORMED:
+		case SOUP_STATUS_BAD_REQUEST: /* 400 */
 			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
 				     /* Translators: the parameter is an error message returned by the server. */
 				     _("Invalid request URI or header, or unsupported nonstandard parameter: %s"), response_body);
 			return;
-		case 401:
-		case 403:
+		case SOUP_STATUS_UNAUTHORIZED: /* 401 */
+		case SOUP_STATUS_FORBIDDEN: /* 403 */
 			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
 				     /* Translators: the parameter is an error message returned by the server. */
 				     _("Authentication required: %s"), response_body);
 			return;
-		case 404:
+		case SOUP_STATUS_NOT_FOUND: /* 404 */
 			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NOT_FOUND,
 				     /* Translators: the parameter is an error message returned by the server. */
 				     _("The requested resource was not found: %s"), response_body);
 			return;
-		case 409:
-		case 412:
+		case SOUP_STATUS_CONFLICT: /* 409 */
+		case SOUP_STATUS_PRECONDITION_FAILED: /* 412 */
 			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_CONFLICT,
 				     /* Translators: the parameter is an error message returned by the server. */
 				     _("The entry has been modified since it was downloaded: %s"), response_body);
 			return;
-		case 500:
+		case SOUP_STATUS_INTERNAL_SERVER_ERROR: /* 500 */
 		default:
 			/* We'll fall back to generic errors, below */
 			break;
@@ -364,6 +377,11 @@ real_parse_error_response (GDataService *self, GDataOperationType operation_type
 
 	/* If the error hasn't been handled already, throw a generic error */
 	switch (operation_type) {
+		case GDATA_OPERATION_AUTHENTICATION:
+			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
+			             /* Translators: the first parameter is an HTTP status, and the second is an error message returned by the server. */
+			             _("Error code %u when authenticating: %s"), status, response_body);
+			break;
 		case GDATA_OPERATION_QUERY:
 			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
 				     /* Translators: the first parameter is an HTTP status, and the second is an error message returned by the server. */
@@ -748,8 +766,9 @@ login_error:
 	return retval;
 
 protocol_error:
-	g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
-			     _("The server returned a malformed response."));
+	g_assert (klass->parse_error_response != NULL);
+	klass->parse_error_response (self, GDATA_OPERATION_AUTHENTICATION, status, message->reason_phrase, message->response_body->data,
+	                             message->response_body->length, error);
 
 general_error:
 	g_object_unref (message);
diff --git a/gdata/gdata-service.h b/gdata/gdata-service.h
index 35d15f6..a2ac3c5 100644
--- a/gdata/gdata-service.h
+++ b/gdata/gdata-service.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
  * @GDATA_OPERATION_DELETION: a deletion of a #GDataEntry
  * @GDATA_OPERATION_DOWNLOAD: a download of a file
  * @GDATA_OPERATION_UPLOAD: an upload of a file
+ * @GDATA_OPERATION_AUTHENTICATION: authentication with the service
  *
  * Representations of the different operations performed by the library.
  *
@@ -47,12 +48,13 @@ typedef enum {
 	GDATA_OPERATION_UPDATE,
 	GDATA_OPERATION_DELETION,
 	GDATA_OPERATION_DOWNLOAD,
-	GDATA_OPERATION_UPLOAD
+	GDATA_OPERATION_UPLOAD,
+	GDATA_OPERATION_AUTHENTICATION
 } GDataOperationType;
 
 /**
  * GDataServiceError:
- * @GDATA_SERVICE_ERROR_UNAVAILABLE: The service is unavailable due to maintainence or other reasons
+ * @GDATA_SERVICE_ERROR_UNAVAILABLE: The service is unavailable due to maintainence or other reasons (e.g. network errors at the server end)
  * @GDATA_SERVICE_ERROR_PROTOCOL_ERROR: The client or server unexpectedly strayed from the protocol (fatal error)
  * @GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED: An entry has already been inserted, and cannot be re-inserted
  * @GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED: The user attempted to do something which required authentication, and they weren't authenticated
@@ -61,6 +63,8 @@ typedef enum {
  * and uploading the modified entry
  * @GDATA_SERVICE_ERROR_FORBIDDEN: Generic error for a forbidden action (not due to having insufficient permissions)
  * @GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER: A given query parameter was invalid for the query type
+ * @GDATA_SERVICE_ERROR_NETWORK_ERROR: The service is unavailable due to local network errors (e.g. no Internet connection)
+ * @GDATA_SERVICE_ERROR_PROXY_ERROR: The service is unavailable due to proxy network errors (e.g. proxy unreachable)
  *
  * Error codes for #GDataService operations.
  **/
@@ -72,7 +76,9 @@ typedef enum {
 	GDATA_SERVICE_ERROR_NOT_FOUND,
 	GDATA_SERVICE_ERROR_CONFLICT,
 	GDATA_SERVICE_ERROR_FORBIDDEN,
-	GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER
+	GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER,
+	GDATA_SERVICE_ERROR_NETWORK_ERROR,
+	GDATA_SERVICE_ERROR_PROXY_ERROR
 } GDataServiceError;
 
 /**
diff --git a/gdata/tests/general.c b/gdata/tests/general.c
index a973eb4..a1c254c 100644
--- a/gdata/tests/general.c
+++ b/gdata/tests/general.c
@@ -646,6 +646,33 @@ test_query_etag (void)
 }
 
 static void
+test_service_network_error (void)
+{
+	GDataService *service;
+	SoupURI *proxy_uri;
+	GError *error = NULL;
+
+	/* This is a little hacky, but it should work */
+	service = g_object_new (GDATA_TYPE_SERVICE, "client-id", CLIENT_ID, NULL);
+
+	/* Try a query which should always fail due to errors resolving the hostname */
+	g_assert (gdata_service_query (service, "http://thisshouldnotexist.localhost";, NULL, GDATA_TYPE_ENTRY, NULL, NULL, NULL, &error) == NULL);
+	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NETWORK_ERROR);
+	g_clear_error (&error);
+
+	/* Try one with a bad proxy set */
+	proxy_uri = soup_uri_new ("http://thisshouldalsonotexist.localhost/proxy";);
+	gdata_service_set_proxy_uri (service, proxy_uri);
+	soup_uri_free (proxy_uri);
+
+	g_assert (gdata_service_query (service, "http://google.com";, NULL, GDATA_TYPE_ENTRY, NULL, NULL, NULL, &error) == NULL);
+	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROXY_ERROR);
+	g_clear_error (&error);
+
+	g_object_unref (service);
+}
+
+static void
 test_access_rule_get_xml (void)
 {
 	GDataAccessRule *rule, *rule2;
@@ -2319,16 +2346,22 @@ main (int argc, char *argv[])
 	g_test_init (&argc, &argv, NULL);
 	g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=";);
 
+	g_test_add_func ("/service/network_error", test_service_network_error);
+
 	g_test_add_func ("/entry/get_xml", test_entry_get_xml);
 	g_test_add_func ("/entry/parse_xml", test_entry_parse_xml);
 	g_test_add_func ("/entry/error_handling", test_entry_error_handling);
+
 	g_test_add_func ("/feed/parse_xml", test_feed_parse_xml);
 	g_test_add_func ("/feed/error_handling", test_feed_error_handling);
+
 	g_test_add_func ("/query/categories", test_query_categories);
 	g_test_add_func ("/query/unicode", test_query_unicode);
 	g_test_add_func ("/query/etag", test_query_etag);
+
 	g_test_add_func ("/access-rule/get_xml", test_access_rule_get_xml);
 	g_test_add_func ("/access-rule/error_handling", test_access_rule_error_handling);
+
 	g_test_add_func ("/color/parsing", test_color_parsing);
 	g_test_add_func ("/color/output", test_color_output);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]