Search code examples
python-3.xkeyerror

KeyError when trying to send body to API via function parameter


Attempting to send a POST request to an API via a python function, and I'm unable to iterate through a list of strings and pass strings into the function.

Successfully tested this out in Postman (the request sends a string to the API in the form of "raw Body" as shown in Postman). Copied the code over from Postman to Python, and verified that also works. The problem is that if I change the static string to the function's parameter, I get a KeyError, however if I simply replace the parameter (which is a value, not a key), to a string, then the keyerror goes away.

This works...

payload = "{\"ids\":[\"cb5f9a97c0e749ab67409e78b4fcb11d\"]}" works

But none of these work (note the error code to the right); especially the first two that are exactly the same as above...

payload = "{\"ids\":[\"{0}\"]}".format(id) #gives KeyError: '"ids"'
payload = "{\"ids\":[{0}]}".format(id) #gives KeyError: '"ids"'
payload = "{'ids':'[{0}]'}".format(id) #gives KeyError: "'ids'"
payload = "{ids:[\"{0}\"]}".format(id) #gives KeyError: 'ids'

I also tried to modify the key ('ids') within the key/value pair, which resulted in NameErrors. Since this deviates from the known working example above, I don't think the below attempts are worth continuing to try...

payload = {ids:"[{0}]".format(id)} #gives NameError: name 'ids' is not defined
payload = {ids:"{0}".format(id)} #gives NameError: name 'ids' is not defined
payload = {ids:id} #gives NameError: name 'ids' is not defined

I even verified that the string produced from the list is in fact a string.

Full (relevant) code below:

def cs_delete(id):
    print(id)
    url = "https://api.crowdstrike.com/devices/entities/devices-actions/v2"
    querystring = {"action_name":"hide_host"}
    payload = "{'ids':['{0}']}".format(id)
    headers = {
    'Content-Type': "application/json",
    'Authorization': "Bearer " + cs_auth,
    'Accept': "*/*",
    'Cache-Control': "no-cache",
    'Host': "api.crowdstrike.com",
    'Accept-Encoding': "gzip, deflate",
    'Content-Length': "83",
    'Connection': "keep-alive",
    'cache-control': "no-cache"
    }
    response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
    print(response.text)

for host in dfList:
    print(host)
    cs_delete(host)

And for completeness, dfList shows as:

['2a9cf64988e6464f7d2ba7f305a612f3', '5ba4654e1dbe418f7b6361582e3d8f47', '7c6fc20572c241f664813f48bb36c340', 'ccbaf1ebe52042fc6b8269bf86732676']

Solution

  • double the outer curly bracket to escape it or format() will expect the input value should be applied for outer curly bracket rather than {0}

    >>> id = 'cb5f9a97c0e749ab67409e78b4fcb11d'
    >>> "{{'ids':[{0}]}}".format(id)
    "{'ids':[cb5f9a97c0e749ab67409e78b4fcb11d]}"