0

I'm trying to connect via json-rpc to the trytond isntance using this class

class HttpClient:
    """HTTP Client to make JSON RPC requests to Tryton server.
    User is logged in when an object is created.
    """

    def __init__(self, url, database_name, user, passwd):
        self._url = '{}/{}/'.format(url, database_name)
        self._user = user
        self._passwd = passwd
        self._login()
        self._id = 0

    def get_id(self):
        self._id += 1
        return self._id

    def _login(self):
        """
        Returns list, where
        0 - user id
        1 - session token
        """
        payload = json.dumps({
            'params': [self._user, {'password': self._passwd}],
            'jsonrpc': "2.0",
            'method': 'common.db.login',
            'id': 1,
        })
        headers = {'content-type': 'application/json'}
        result = requests.post(self._url, data=payload, headers=headers)
        if result.status_code in [500, 401]:
            raise Exception(result.text)

        if 'json' in result:
            self._session = result.json()['result']
        else:
            self._session = json.loads(result.text)

        return self._session

    def call(self, prefix, method, params=[[], {}]):
        """RPC Call
        """
        method = '{}.{}'.format(prefix, method)
        payload = json.dumps({
            'params': params,
            'method': method,
            'id': self.get_id(),

        })

        authorization = base64.b64encode(self._session[1].encode('utf-8'))
        headers = {
        'Content-Type': 'application/json',
        'Authorization': b'Session ' + authorization
        }

        response = requests.post(self._url, data=payload, headers=headers)
        if response.status_code in [500, 401]:
            raise Exception(response.text)
        return response.json()

    def model(self, model, method, args=[], kwargs={}):
        return self.call('model.%s' % model, method, [args, kwargs])

    def system(self, method):
        return self.call('system', method, params=[])

and I call it in this way

def notifieToMainServer(self):
    url = "http://%s:%s" % (HOST, PORT)
    headers = {'content-type': 'application/json'}
    client = HttpClient(url, "tryton", CREDENTIALS[0], CREDENTIALS[1])   
    client.model('main.register',
                 'ActivateService', 
                 {'code': self.code,
                  'name': self.nome,
                  'surname': self.cognome,
                  'service_type': 'registry',
                  'service_url': '' # qui andra messa l'url di chimata
                  }
                 )

the creatin of the HttpClient works well and I'm able to login, but when I try to call the method ActivateService I recive a 401 responce.

I also add the ActivateService into the rpc class

@classmethod
def __setup__(cls):
    super(MainRegister, cls).__setup__()
    cls.__rpc__.update({    
            'ActivateService': RPC(instantiate=0)})  

and the function is like

def ActivateService(self,
                    code,
                    name,
                    surname,
                    service_type,
                    service_url):
    """
        activate the service for the given code and the given service
    """

what I did wrong ?

best regards, Matteo

Mehdi
  • 717
  • 1
  • 7
  • 21
  • Did you have the server logs? 401 means that there is some Error on the server. Probably having a look at it will lead you to the cause of the error. Otherwise please share them so we are able to help – pokoli Feb 18 '20 at 08:18
  • Unfortunately I'do not have ant error in the response.text when the exception is raised – Matteo Boscolo Feb 18 '20 at 22:36

2 Answers2

1

The Authorization header should be:

'Authorization': : b'Bearer ' + authorization

ced
  • 229
  • 1
  • 7
  • I found the problem with the authorisation header now, and I solve it using this code: auth = "%s:%s:%s" % (self._user, self._session[0], self._session[1]) authorization = base64.b64encode(auth.encode('utf-8')) headers = { 'Content-Type': 'application/json', 'Authorization': b'Session ' + authorization } Now I get a problem with the args that are switched in the context, so the call of the function field – Matteo Boscolo Feb 19 '20 at 10:07
0

At the and I finally solve the problem with this modifies class

class HttpClient:
    """HTTP Client to make JSON RPC requests to Tryton server.
    User is logged in when an object is created.
    """

    def __init__(self, url, database_name, user, passwd):
        self._url = '{}/{}/'.format(url, database_name)
        self._user = user
        self._passwd = passwd
        self._login()
        self._id = 0

    def get_id(self):
        self._id += 1
        return self._id

    def _login(self):
        """
        Returns list, where
        0 - user id
        1 - session token
        """
        payload = json.dumps({
            'params': [self._user, {'password': self._passwd}],
            'jsonrpc': "2.0",
            'method': 'common.db.login',
            'id': 1,
        })
        headers = {'content-type': 'application/json'}
        result = requests.post(self._url,
                               data=payload,
                               headers=headers)
        if result.status_code in [500, 401]:
            raise Exception(result.text)

        if 'json' in result:
            self._session = result.json()['result']
        else:
            self._session = json.loads(result.text)

        return self._session

    def call(self, prefix, method, params=[[], {}, {}]):
        """RPC Call
        """
        method = '{}.{}'.format(prefix, method)
        payload = json.dumps({
            'params': params,
            'method': method,
            'id': self.get_id(),
         })
        auth = "%s:%s:%s" % (self._user, self._session[0], self._session[1])
        authorization = base64.b64encode(auth.encode('utf-8'))
        headers = {
        'Content-Type': 'application/json',
        'Authorization': b'Session ' + authorization
        }

        response = requests.post(self._url,
                                 data=payload,
                                 headers=headers)
        if response.status_code in [500, 401]:
            raise Exception(response.text)
        return response.json()

    def model(self, model, method, args=[], kwargs={}):
        return self.call('model.%s' % model, method, (args, kwargs, {}))

    def system(self, method):
        return self.call('system', method, params=[])

the key point is the call that must be done with the context in order to be executed in the right way !!

    def model(self, model, method, args=[], kwargs={}):
        return self.call('model.%s' % model, method, (args, kwargs, {}))

hope it helps regards