1

I'm working with Microsoft Graph API via Python 3 and Requests. The following code works:

r = graph_session.get(graph_endpoint + '''/groups?$filter=groupTypes/any(c:c+eq+'Unified')''')
print(r.url)

>>> https://graph.microsoft.com/v1.0/groups?$filter=groupTypes/any(c:c+eq+'Unified')

However, this does not work:

parameters = {'$filter': '''groupTypes/any(c:c+eq+'Unified')'''}
r = graph_session.get(graph_endpoint + '/groups', params=parameters)
print(r.url)

>>> https://graph.microsoft.com/v1.0/groups?%24filter=groupTypes%2Fany%28c%3Ac%2Beq%2B%27Unified%27%29

Why does the latter method, which seems to be cleaner, produce a 400 error (Bad request)? It seems like an encoding problem.

bendodge
  • 470
  • 5
  • 12
  • Is it the position of ending quote of `Unified`? `parameters = {'$filter': '''groupTypes/any(c:c+eq+'Unified')'''}` – Kamal May 21 '19 at 07:52
  • @Kamal I don't think so. It should end up as `$filter=groupTypes/any(c:c+eq+'Unified')` – bendodge May 21 '19 at 15:55
  • Yes, you have used that in your working case, but in not-working case, you have done `...'Unified)''''`, which is ending as `...%27Unified%29%27`. But you want it as `...%27Unified%27%29` – Kamal May 22 '19 at 02:09
  • @Kamal Oops, that was just a typo. (I tried again just to be sure; it doesn't work.) I edited the post; thanks. – bendodge May 23 '19 at 14:55

1 Answers1

1

It seems like an encoding problem.

Indeed it is, in that case filter expression is getting encoded (which is by design) and Microsoft Graph returns the following error:

{
    "error": {
        "code": "BadRequest",
        "message": "Invalid filter clause",
        //...
    }
}

The encoding could be prevented if params argument is passed as a string:

parameters = {'$filter': '''groupTypes/any(c:c+eq+'Unified')'''}
parameters_str = "&".join("%s=%s" % (k, v) for k, v in parameters.items())
r = graph_session.get(graph_endpoint + '/groups', params=parameters_str, headers=headers)

Refer this answer for another options.

Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • 1
    Thank you! Although less flexible, `parameters = '''$filter:groupTypes/any(c:c+eq+'Unified')'''` also works. Additionally, the [docs](https://2.python-requests.org//en/master/user/quickstart/#more-complicated-post-requests) mention that passing a string will avoid form-encoding. I didn't know the magic words "form-encoded" and "url encoding." – bendodge May 23 '19 at 22:12