@@ -47,14 +47,17 @@ typedef struct {
4747}ds3_xml_send_buff ;
4848
4949typedef struct {
50+ // These attributes are used when processing a response header
5051 uint64_t status_code ;
5152 char * status_message ;
5253 size_t status_message_size ;
5354 size_t header_count ;
5455 GHashTable * headers ;
55- GByteArray * body ; // this will only be used when getting errors
5656
57+ // These attributes are used when processing a response body
58+ GByteArray * body ; // this will only be used when getting errors
5759 void * user_data ;
60+ size_t (* user_func )(void * , size_t , size_t , void * );
5861}ds3_response_data ;
5962
6063typedef struct {
@@ -101,6 +104,14 @@ static size_t _ds3_send_xml_buff(void* buffer, size_t size, size_t nmemb, void*
101104 return to_read ;
102105}
103106
107+ static size_t load_buffer (void * buffer , size_t size , size_t nmemb , void * user_data ) {
108+ size_t realsize = size * nmemb ;
109+ GByteArray * blob = (GByteArray * ) user_data ;
110+
111+ g_byte_array_append (blob , (const guint8 * ) buffer , realsize );
112+ return realsize ;
113+ }
114+
104115static size_t _process_header_line (void * buffer , size_t size , size_t nmemb , void * user_data ) {
105116 size_t to_read ;
106117 char * header_buff ;
@@ -181,6 +192,18 @@ static size_t _process_header_line(void* buffer, size_t size, size_t nmemb, void
181192 return to_read ;
182193}
183194
195+ static size_t _process_response_body (void * buffer , size_t size , size_t nmemb , void * user_data ) {
196+ ds3_response_data * response_data = (ds3_response_data * ) user_data ;
197+
198+ // If we got an error, collect the error body
199+ if (response_data -> status_code >= 400 ) {
200+ return load_buffer (buffer , size , nmemb , response_data -> body );
201+ }
202+ else { // If we did not get an error, call he user's defined callbacks.
203+ return response_data -> user_func (buffer , size , nmemb , response_data -> user_data );
204+ }
205+ }
206+
184207//---------- Networking code ----------//
185208static void _init_curl (void ) {
186209 static ds3_bool initialized = False ;
@@ -283,7 +306,7 @@ static char* _net_gen_query_params(GHashTable* query_params) {
283306
284307 return_string = g_strjoinv ("&" , entries );
285308
286- for (i = 0 ; ; i ++ ) {
309+ for (i = 0 ; ; i ++ ) {
287310 char * current_string = entries [i ];
288311 if (current_string == NULL ) {
289312 break ;
@@ -319,8 +342,8 @@ static ds3_error* _net_process_request(const ds3_client* client, const ds3_reque
319342 GHashTable * response_headers = g_hash_table_new_full (g_str_hash , g_str_equal , NULL , _ds3_free_response_header );
320343
321344 memset (& response_data , 0 , sizeof (ds3_response_data ));
322-
323345 response_data .headers = response_headers ;
346+ response_data .body = g_byte_array_new ();
324347
325348 if (query_params == NULL ) {
326349 url = g_strconcat (client -> endpoint , request -> path , NULL );
@@ -343,10 +366,14 @@ static ds3_error* _net_process_request(const ds3_client* client, const ds3_reque
343366
344367 // Register the read and write handlers if they are set
345368 if (read_user_struct != NULL && read_handler_func != NULL ) {
346- curl_easy_setopt ( handle , CURLOPT_WRITEFUNCTION , read_handler_func ) ;
347- curl_easy_setopt ( handle , CURLOPT_WRITEDATA , read_user_struct ) ;
369+ response_data . user_data = read_user_struct ;
370+ response_data . user_func = read_handler_func ;
348371 }
349372
373+ // We must always set this so we can collect the error message body
374+ curl_easy_setopt (handle , CURLOPT_WRITEFUNCTION , _process_response_body );
375+ curl_easy_setopt (handle , CURLOPT_WRITEDATA , & response_data );
376+
350377 if (write_user_struct != NULL && write_handler_func != NULL ) {
351378 curl_easy_setopt (handle , CURLOPT_READFUNCTION , write_handler_func );
352379 curl_easy_setopt (handle , CURLOPT_READDATA , write_user_struct );
@@ -418,10 +445,14 @@ static ds3_error* _net_process_request(const ds3_client* client, const ds3_reque
418445 error -> error -> status_code = response_data .status_code ;
419446 error -> error -> status_message = g_strdup (response_data .status_message );
420447 error -> error -> status_message_size = strlen (error -> error -> status_message );
448+ error -> error -> error_body = g_strdup (response_data .body -> data );
449+ error -> error -> error_body_size = response_data .body -> len ;
421450
451+ g_byte_array_free (response_data .body , TRUE);
422452 g_free (response_data .status_message );
423453 return error ;
424454 }
455+ g_byte_array_free (response_data .body , TRUE);
425456 g_free (response_data .status_message );
426457 if (res != CURLE_OK ) {
427458 char * message = g_strconcat ("Request failed: " , curl_easy_strerror (res ), NULL );
@@ -579,13 +610,6 @@ static ds3_error* _internal_request_dispatcher(const ds3_client* client, const d
579610 return _net_process_request (client , request , read_user_struct , read_handler_func , write_user_struct , write_handler_func );
580611}
581612
582- static size_t load_xml_buff (void * contents , size_t size , size_t nmemb , void * user_data ) {
583- size_t realsize = size * nmemb ;
584- GByteArray * blob = (GByteArray * ) user_data ;
585-
586- g_byte_array_append (blob , (const guint8 * ) contents , realsize );
587- return realsize ;
588- }
589613
590614static void _parse_buckets (xmlDocPtr doc , xmlNodePtr buckets_node , ds3_get_service_response * response ) {
591615 xmlChar * text ;
@@ -656,7 +680,7 @@ ds3_error* ds3_get_service(const ds3_client* client, const ds3_request* request,
656680 ds3_error * error ;
657681 GByteArray * xml_blob = g_byte_array_new ();
658682
659- error = _internal_request_dispatcher (client , request , xml_blob , load_xml_buff , NULL , NULL );
683+ error = _internal_request_dispatcher (client , request , xml_blob , load_buffer , NULL , NULL );
660684
661685 if (error != NULL ) {
662686 g_byte_array_free (xml_blob , TRUE);
@@ -774,7 +798,7 @@ ds3_error* ds3_get_bucket(const ds3_client* client, const ds3_request* request,
774798 xmlChar * text ;
775799 GArray * object_array = g_array_new (FALSE, TRUE, sizeof (ds3_object ));
776800 GByteArray * xml_blob = g_byte_array_new ();
777- _internal_request_dispatcher (client , request , xml_blob , load_xml_buff , NULL , NULL );
801+ _internal_request_dispatcher (client , request , xml_blob , load_buffer , NULL , NULL );
778802
779803 doc = xmlParseMemory ((const char * ) xml_blob -> data , xml_blob -> len );
780804 if (doc == NULL ) {
@@ -1069,7 +1093,7 @@ ds3_error* ds3_bulk(const ds3_client* client, const ds3_request* _request, ds3_b
10691093 request -> length = send_buff .size ; // make sure to set the size of the request.
10701094
10711095 xml_blob = g_byte_array_new ();
1072- error_response = _net_process_request (client , request , xml_blob , load_xml_buff , (void * ) & send_buff , _ds3_send_xml_buff );
1096+ error_response = _net_process_request (client , request , xml_blob , load_buffer , (void * ) & send_buff , _ds3_send_xml_buff );
10731097
10741098 // Cleanup the data sent to the server.
10751099 xmlFreeDoc (doc );
0 commit comments