source: ogAgent-Git/src/opengnsys/RESTApi.py @ 97a3b4e

configure-ptt-chedecorare-oglive-methodsejecutarscript-b64fix-cfg2objfixes-winlgromero-filebeatmainmodulesnew-browserno-ptt-paramogadmcliogadmclient-statusogagent-jobsogagent-macosogcore1ogliveoglogoglog2override-moduleping1ping2ping3ping4py3-winpython3qndtestreport-progresstlsunification2unification3versionswindows-fixes
Last change on this file since 97a3b4e was 11f7a07, checked in by ramon <ramongomez@…>, 9 years ago

#718: Integrar código fuente de agente OGAgent en rama de desarrollo.

git-svn-id: https://opengnsys.es/svn/branches/version1.1@4865 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 6.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 201 Virtual Cable S.L.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#    * Redistributions of source code must retain the above copyright notice,
10#      this list of conditions and the following disclaimer.
11#    * Redistributions in binary form must reproduce the above copyright notice,
12#      this list of conditions and the following disclaimer in the documentation
13#      and/or other materials provided with the distribution.
14#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
15#      may be used to endorse or promote products derived from this software
16#      without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29'''
30@author: Adolfo Gómez, dkmaster at dkmon dot com
31'''
32
33# pylint: disable-msg=E1101,W0703
34
35from __future__ import unicode_literals
36
37import requests
38import logging
39import json
40import warnings
41
42from .log import logger
43
44from .utils import exceptionToMessage
45
46VERIFY_CERT = False
47
48
49class RESTError(Exception):
50    ERRCODE = 0
51
52
53class ConnectionError(RESTError):
54    ERRCODE = -1
55
56
57# Disable warnings log messages
58try:
59    import urllib3  # @UnusedImport
60except Exception:
61    from requests.packages import urllib3  # @Reimport
62
63try:
64    urllib3.disable_warnings()  # @UndefinedVariable
65    warnings.simplefilter("ignore")
66except Exception:
67    pass  # In fact, isn't too important, but wil log warns to logging file
68
69class REST(object):
70    '''
71    Simple interface to remote REST apis.
72    The constructor expects the "base url" as parameter, that is, the url that will be common on all REST requests
73    Remember that this is a helper for "easy of use". You can provide your owns using requests lib for example.
74    Examples:
75       v = REST('https://example.com/rest/v1/') (Can omit trailing / if desired)
76       v.sendMessage('hello?param1=1&param2=2')
77         This will generate a GET message to https://example.com/rest/v1/hello?param1=1&param2=2, and return the deserialized JSON result or an exception
78       v.sendMessage('hello?param1=1&param2=2', {'name': 'mario' })
79         This will generate a POST message to https://example.com/rest/v1/hello?param1=1&param2=2, with json encoded body {'name': 'mario' }, and also returns
80         the deserialized JSON result or raises an exception in case of error
81    '''
82    def __init__(self, url):
83        '''
84        Initializes the REST helper
85        url is the full url of the REST API Base, as for example "https://example.com/rest/v1".
86        @param url The url of the REST API Base. The trailing '/' can be included or omitted, as desired.
87        '''
88        self.endpoint = url
89       
90        if self.endpoint[-1] != '/':
91            self.endpoint += '/'
92       
93        # Some OSs ships very old python requests lib implementations, workaround them...
94        try:
95            self.newerRequestLib = requests.__version__.split('.')[0] >= '1'
96        except Exception:
97            self.newerRequestLib = False  # I no version, guess this must be an old requests
98
99        # Disable logging requests messages except for errors, ...
100        logging.getLogger("requests").setLevel(logging.CRITICAL)
101        # Tries to disable all warnings
102        try:
103            warnings.simplefilter("ignore")  # Disables all warnings
104        except Exception:
105            pass
106
107    def _getUrl(self, method):
108        '''
109        Internal method
110        Composes the URL based on "method"
111        @param method: Method to append to base url for composition
112        '''
113        url = self.endpoint + method
114
115        return url
116
117    def _request(self, url, data=None):
118        '''
119        Launches the request
120        @param url: The url to obtain
121        @param data: if None, the request will be sent as a GET request. If != None, the request will be sent as a POST, with data serialized as JSON in the body.
122        '''
123        try:
124            if data is None:
125                logger.debug('Requesting using GET (no data provided) {}'.format(url))
126                # Old requests version does not support verify, but they do not checks ssl certificate by default
127                if self.newerRequestLib:
128                    r = requests.get(url, verify=VERIFY_CERT)
129                else:
130                    r = requests.get(url)
131            else: # POST
132                logger.debug('Requesting using POST {}, data: {}'.format(url, data))
133                if self.newerRequestLib:
134                    r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT)
135                else:
136                    r = requests.post(url, data=data, headers={'content-type': 'application/json'})
137
138            r = json.loads(r.content)  # Using instead of r.json() to make compatible with oooold rquests lib versions
139        except requests.exceptions.RequestException as e:
140            raise ConnectionError(e)
141        except Exception as e:
142            raise ConnectionError(exceptionToMessage(e))
143
144        return r
145
146    def sendMessage(self, msg, data=None, processData=True):
147        '''
148        Sends a message to remote REST server
149        @param data: if None or omitted, message will be a GET, else it will send a POST
150        @param processData: if True, data will be serialized to json before sending, else, data will be sent as "raw"
151        '''
152        logger.debug('Invoking post message {} with data {}'.format(msg, data))
153
154        if processData and data is not None:
155            data = json.dumps(data)
156           
157        url = self._getUrl(msg)
158        logger.debug('Requesting {}'.format(url))
159       
160        return self._request(url, data)
Note: See TracBrowser for help on using the repository browser.