简体   繁体   中英

how to properly call a REST-API with an * in the URL

i searched the internet (and stackoverflow:D) to find an answer for the following question - and found none that i understood .

background:
we want to use a python script to connect our companies CMDB with our AWX/Ansible infrastructure.
the CMDB has a REST API which supports a (halfway) proper export.
i'm currently stuck with the implementation of the correct API call.
i can call the API itself and authenticate, but i can't call the proper filter to get the results i need.
the filter is realized by having the following string within the URL (more in the attached code example)

Label LIKE "host*"

it seems that python has a problem with the *.
error message:

InvalidURL(f"URL can't contain control characters. {url!r} "


I found some bug reports that there is an issue within some python versions, but i'm way to new to properly understand if this affects me here:D

used python version 3.7.4

PS: let's see if i can get the markup right:D


i switched the called URL to determine where exactly the problem occurs.
it only occurs when i use the SQL like filter part.
this part is essential since i just want our "hosts" to be returned and not the whole CMDB itself.


#import the required classes and such
from http.client import HTTPConnection
import json
#create a HTTP connection client
client = HTTPConnection("cmdb.example.company")
#basic auth and some header details
headers = {'Content-Type': 'application/json',
           'Authorization' : 'Basic my-auth-token'}
#working API call
client.request('GET', '/cmdb/rest/hosts?attributes=Label,Keywords,Tag,Description&limit=10', headers=headers)

#broken API call returns - InvalidURL(f"URL can't contain control characters. {url!r} "
client.request('GET', '/cmdb/rest/hosts?filter=Label LIKE "host*"&attributes=Label,Keywords,Tag,Description&limit=10', headers=headers)
#check and convert the response into a readable (JSON) format
response = client.getresponse()
data = response.read()

#debugging print - show that the returned data is bytes?!
print(data)

#convert the returned data into json
my_json = data.decode('utf8').replace("'", '"')
data = json.loads(my_json)

#only return the data part from the JSON and ignore the meta-overhead
text = json.dumps(data["data"], sort_keys=True, indent=4)
print(text)

so, i want to know how to properly call the API with the described filter and resolve the displayed error.
can you give me an example i can try or pin-point a beginners mistake i made?
am i affected by the mentioned python bug regarding the URL call with * in it?

thanks for helping me out:)

soooo i found my beginners mistake myself:

i used the URL from my browser - and my browser automaticly encodes the special characters within the URL.
i found the following piece of code within Python3 URL encoding guide and modified the string to fit my needs:)

import urllib.parse
query = ' "host*"'
urllib.parse.quote(query)
'%20%22host%2A%22'


Result: '%20%22host%2A%22'
%20 = " "
%22 = " " "
%2A = "*"

so the final code looks somewhat like this:

#broken API call returns - InvalidURL(f"URL can't contain control characters. {url!r} "
client.request('GET', '/cmdb/rest/hosts?filter=Label LIKE "host*"&attributes=Label,Keywords,Tag,Description&limit=10', headers=headers)

filter=Label LIKE "host*"

#fixed API call
client.request('GET', '/cmdb/rest/hosts?filter=Label%20LIKE%20%22host%2A%22&attributes=Label,Keywords,Tag,Description&limit=10', headers=headers)

filter=Label%20LIKE%20%22host%2A%22

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM