python-pyodata icon indicating copy to clipboard operation
python-pyodata copied to clipboard

href of entity set respected?

Open rene312 opened this issue 4 years ago • 5 comments

Hello,

I am trying to access the entity set “APIs” of https://api.sap.com/odata/1.0/catalog.svc/

If I execute https://api.sap.com/odata/1.0/catalog.svc/ in the browser I get

APIs

However if I execute

client.entity_sets.APIs.get_entities().execute()

in python while tracing the url’s I see:

https://api.sap.com:443 "GET /odata/1.0/catalog.svc/APIs HTTP/1.1" 200 None

this naturally does not work as the URL path should be https://api.sap.com/odata/1.0/catalog.svc/APIContent.APIs/ (which does work in the browser).

Am I using the API wrong? What should I be executing instead of client.entity_sets.APIs.get_entities().execute() ?

Best regards, Rene.

rene312 avatar Jul 14 '21 09:07 rene312

Hi @rene312, could you please enable logging and provide the request and the response: https://pyodata.readthedocs.io/en/latest/usage/advanced.html#enable-logging

If from logging will be apparent that it is certificate problem (just a guess from the info so far), check https://pyodata.readthedocs.io/en/latest/usage/initialization.html

phanak-sap avatar Jul 19 '21 20:07 phanak-sap

py_odata_trace.txt Hi Phanak, I have attached the trace. There are no authorization problems before the access of the invalid url https://api.sap.com/odata/1.0/catalog.svc/APIs. I also spoke to the person responsible for the security of https://api.sap.com/odata/1.0/catalog.svc/ and he stated that no authorization / logon / certificates are required to access the resources. I have also verified this in a sandboxed browser with no certificates installed. However attempting to access invalid url's seems to trigger SAML authentication. I have not found a way to suppress this. i.e. does the library attempt to access the invalid url /odata/1.0/catalog.svc/APIs and only if that fails access the correct one https://api.sap.com/odata/1.0/catalog.svc/APIContent.APIs/ ? I am not sure if I can get this working if the library does that. Best regards, Rene.

rene312 avatar Jul 20 '21 12:07 rene312

Hi Phanak,

Search through the trace, I see that we have <EntityContainer Name="APIContent"><EntitySet Name="APIs" EntityType="APIContent.API">

Though client.entity_sets.APIs exists as method.

Rene.

rene312 avatar Jul 20 '21 12:07 rene312

Ooops, PyOData supports only 1 schema per Metadata: https://github.com/SAP/python-pyodata/blob/3975ed5365b55936872d8e6722545fdf2c481e80/pyodata/v2/model.py#L2601

jfilak avatar Jul 21 '21 13:07 jfilak

I am not so familiar with oData or Python, but the following worked in my case. Don't know if it breaks other cases:

I added the lines

    if alias is None:
        self._alias = entity_set._entity_type_info.namespace + '.' + entity_set.name    
    else:    
        self._alias = alias

to method def init of class EntitySetProxy as shown below.

class EntitySetProxy: """EntitySet Proxy"""

def __init__(self, service, entity_set, alias=None, parent_last_segment=None):
    """Creates new Entity Set object

        @param alias  in case the entity set is access via assossiation
        @param parent_last_segment  in case of association also parent key must be used
    """
    self._service = service
    self._entity_set = entity_set
    if alias is None:
        self._alias = entity_set._entity_type_info.namespace + '.' + entity_set.name    
    else:    
        self._alias = alias
    if parent_last_segment is None:
        self._parent_last_segment = ''
    else:
        if parent_last_segment.endswith('/'):
            self._parent_last_segment = parent_last_segment
        else:
            self._parent_last_segment = parent_last_segment + '/'
    self._name = entity_set.name
    self._key = entity_set.entity_type.key_proprties
    self._logger = logging.getLogger(LOGGER_NAME)

    self._logger.debug('New entity set proxy instance for %s', self._name)

habbler avatar Aug 27 '21 12:08 habbler