Capture end organize exceptions. Fix NotFound
[osm/osmclient.git] / osmclient / sol005 / http.py
index 11ddca6..3d21465 100644 (file)
 from io import BytesIO
 import pycurl
 import json
-import yaml
+import logging
+import copy
 from osmclient.common import http
-from osmclient.common.exceptions import ClientException
+from osmclient.common.exceptions import OsmHttpException, NotFound
+
 
 class Http(http.Http):
 
@@ -28,10 +30,13 @@ class Http(http.Http):
         self._user = user
         self._password = password
         self._http_header = None
+        self._logger = logging.getLogger('osmclient')
 
     def _get_curl_cmd(self, endpoint):
+        self._logger.debug("")
         curl_cmd = pycurl.Curl()
-        #print self._url + endpoint
+        if self._logger.getEffectiveLevel() == logging.DEBUG:
+            curl_cmd.setopt(pycurl.VERBOSE, True)
         curl_cmd.setopt(pycurl.URL, self._url + endpoint)
         curl_cmd.setopt(pycurl.SSL_VERIFYPEER, 0)
         curl_cmd.setopt(pycurl.SSL_VERIFYHOST, 0)
@@ -40,38 +45,47 @@ class Http(http.Http):
         return curl_cmd
 
     def delete_cmd(self, endpoint):
+        self._logger.debug("")
         data = BytesIO()
         curl_cmd = self._get_curl_cmd(endpoint)
         curl_cmd.setopt(pycurl.CUSTOMREQUEST, "DELETE")
         curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write)
+        self._logger.info("Request METHOD: {} URL: {}".format("DELETE",self._url + endpoint))
         curl_cmd.perform()
         http_code = curl_cmd.getinfo(pycurl.HTTP_CODE)
-        #print 'HTTP_CODE: {}'.format(http_code)
+        self._logger.info("Response HTTPCODE: {}".format(http_code))
         curl_cmd.close()
-        if http_code == 204:
-            return None
-        elif http_code == 404:
-            if data.getvalue():
-                return json.loads(data.getvalue().decode())
-            else:
-                return "NOT FOUND"
+        self.check_http_response(http_code, data)
+        # TODO 202 accepted should be returned somehow
         if data.getvalue():
-            return json.loads(data.getvalue().decode())
-        return "Failed"
+            data_text = data.getvalue().decode()
+            self._logger.verbose("Response DATA: {}".format(data_text))
+            return http_code, data_text
+        else:
+            return http_code, None
 
     def send_cmd(self, endpoint='', postfields_dict=None,
                  formfile=None, filename=None,
-                 put_method=False):
+                 put_method=False, patch_method=False):
+        self._logger.debug("")
         data = BytesIO()
         curl_cmd = self._get_curl_cmd(endpoint)
         if put_method:
-            curl_cmd.setopt(pycurl.PUT, 1)
-        else:
-            curl_cmd.setopt(pycurl.POST, 1)
+            curl_cmd.setopt(pycurl.CUSTOMREQUEST, "PUT")
+        elif patch_method:
+            curl_cmd.setopt(pycurl.CUSTOMREQUEST, "PATCH")
+        curl_cmd.setopt(pycurl.POST, 1)
         curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write)
 
         if postfields_dict is not None:
             jsondata = json.dumps(postfields_dict)
+            if 'password' in postfields_dict:
+                postfields_dict_copy = copy.deepcopy(postfields_dict)
+                postfields_dict_copy['password']='******'
+                jsondata_log = json.dumps(postfields_dict_copy)
+            else:
+                jsondata_log = jsondata
+            self._logger.verbose("Request POSTFIELDS: {}".format(jsondata_log))
             curl_cmd.setopt(pycurl.POSTFIELDS, jsondata)
         elif formfile is not None:
             curl_cmd.setopt(
@@ -80,51 +94,83 @@ class Http(http.Http):
                            (pycurl.FORM_FILE,
                             formfile[1])))])
         elif filename is not None:
-            with open(filename, 'r') as stream:
+            with open(filename, 'rb') as stream:
                 postdata=stream.read()
+            self._logger.verbose("Request POSTFIELDS: Binary content")
             curl_cmd.setopt(pycurl.POSTFIELDS, postdata)
 
+        if put_method:
+            self._logger.info("Request METHOD: {} URL: {}".format("PUT",self._url + endpoint))
+        elif patch_method:
+            self._logger.info("Request METHOD: {} URL: {}".format("PATCH",self._url + endpoint))
+        else:
+            self._logger.info("Request METHOD: {} URL: {}".format("POST",self._url + endpoint))
         curl_cmd.perform()
         http_code = curl_cmd.getinfo(pycurl.HTTP_CODE)
+        self._logger.info("Response HTTPCODE: {}".format(http_code))
         curl_cmd.close()
-        if http_code not in (200, 201, 202, 204):
-            raise ClientException(data.getvalue().decode())
-        if postfields_dict is not None:
-            if data.getvalue():
-                return json.loads(data.getvalue().decode())
-            return None
-        elif formfile is not None:
-            if data.getvalue():
-                return yaml.safe_load(data.getvalue().decode())
-            return None
-        elif filename is not None:
-            if data.getvalue():
-                return yaml.safe_load(data.getvalue().decode())
-            return None
-        return None
+        self.check_http_response(http_code, data)
+        if data.getvalue():
+            data_text = data.getvalue().decode()
+            self._logger.verbose("Response DATA: {}".format(data_text))
+            return http_code, data_text
+        else:
+            return http_code, None
 
     def post_cmd(self, endpoint='', postfields_dict=None,
                  formfile=None, filename=None):
+        self._logger.debug("")
         return self.send_cmd(endpoint=endpoint,
                              postfields_dict=postfields_dict,
                              formfile=formfile,
                              filename=filename,
-                             put_method=False)
+                             put_method=False, patch_method=False)
 
     def put_cmd(self, endpoint='', postfields_dict=None,
                 formfile=None, filename=None):
+        self._logger.debug("")
         return self.send_cmd(endpoint=endpoint,
                              postfields_dict=postfields_dict,
                              formfile=formfile,
                              filename=filename,
-                             put_method=True)
+                             put_method=True, patch_method=False)
+
+    def patch_cmd(self, endpoint='', postfields_dict=None,
+                formfile=None, filename=None):
+        self._logger.debug("")
+        return self.send_cmd(endpoint=endpoint,
+                             postfields_dict=postfields_dict,
+                             formfile=formfile,
+                             filename=filename,
+                             put_method=False, patch_method=True)
 
     def get2_cmd(self, endpoint):
+        self._logger.debug("")
         data = BytesIO()
         curl_cmd = self._get_curl_cmd(endpoint)
         curl_cmd.setopt(pycurl.HTTPGET, 1)
         curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write)
+        self._logger.info("Request METHOD: {} URL: {}".format("GET",self._url + endpoint))
         curl_cmd.perform()
+        http_code = curl_cmd.getinfo(pycurl.HTTP_CODE)
+        self._logger.info("Response HTTPCODE: {}".format(http_code))
         curl_cmd.close()
-        return data.getvalue()
+        self.check_http_response(http_code, data)
+        if data.getvalue():
+            data_text = data.getvalue().decode()
+            self._logger.verbose("Response DATA: {}".format(data_text))
+            return http_code, data_text
+        return http_code, None
 
+    def check_http_response(self, http_code, data):
+        if http_code >= 300:
+            resp = ""
+            if data.getvalue():
+                data_text = data.getvalue().decode()
+                self._logger.verbose("Response {} DATA: {}".format(http_code, data_text))
+                resp = ": " + data_text
+            else:
+                self._logger.verbose("Response {}".format(http_code))
+            if http_code == 404:
+                raise NotFound("Error {}{}".format(http_code, resp))
+            raise OsmHttpException("Error {}{}".format(http_code, resp))