Python http delete requests with URL path variable - python

I have an Http endpoint exposed as http://localhost:8080/test/api/v1/qc/{id} for delete, while making this API delete call I have to replace with the proper id
I tried below way using the requests module of python
param = {
"id" : 1
}
requests.delete(url = http://localhost:8080/test/api/v1/qc/{id}, params=param)
This API call is breaking with the error
ValueError: No JSON object could be decoded.
How can I do this?

Your code can't run as-is. You need to quote your url string:
url = "http://localhost:8080/test/api/v1/qc/{id}"
Reading the docs for requests, the params only sends the dictionary param as the query string, so it'll only tack on ?id=1 to the end of the URL.
What you want is the {id} to get the value from the dictionary. You can look at this answer for various ways: How do I format a string using a dictionary in python-3.x?
You want something like
requests.delete(url = "http://localhost:8080/test/api/v1/qc/{id}".format(**param))

Related

How to convert strings from HTML request to Python objects with FastAPI

I am making my first API; any advice to improve my process is much appreciated.
I plan on passing JSON-like strings into the HTML request to this FastAPI microservice down there
#app.get("/create/{value}")
def createJSON(value:str):
person_json = value.strip()
fileName = person_json['Value']['0'] + person_json['Value']['1']
with open('%s.JSON','w') as writeFile:
writeFile.write(string)
return "Person has been created"
My HTTP request would look like this:
http://127.0.0.1:8000/create/{"Key":{"0":"name","1":"grad_year","2":"major","3":"quarter","4":"pronoun","5":"hobbies","6":"fun_fact","7":"food","8":"clubs","9":"res"},"Value":{"0":"adfasdfa","1":"adf'asd","2":"asd","3":"fads","4":"fa","5":"sdfa","6":"df","7":"asd","8":"fa","9":"df"}}
However, when doing this. The values passed are strings. Thus rendering the fileName portion of the code useless. How can I convert it to a Python dict? I have tried to use .strip(), but it did not help.
You're on the wrong track, Such a request should be essentially modeled as POST or a PUT request. That would allow you to send JSON in the body of the request and obtain it as a dict in python. You can see here
And even if you want to pass data in a GET request, there are query params
Coming back to the original doubt, you would have to use json.loads() to parse the json data and load it in a python dict then you can dump whatever file you like after that.
I'd recommend using the requests library
import requests
url = 'http://127.0.0.1:8000/create/'
params = dict(
name = 'Josh',
grad_year = '1987',
major = 'computer science',
quarter = '3'
)
resp = requests.get(url=url, params=params)
data = resp.json()
Then see here how to handle the JSON Response Content:
https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content
The dict in the code I posted is different than the JSON you're trying to send through though. I assume you have a specific reason for having a "Key" array with the names than a "Value" array for the values of those specific names. But if not I'd recommend using a dictionary instead that way you can do things like:
fileName = person_json['name'] + person_json['grad-year']

How do I parse a specific cookie value?

So let's say that I need to have a CSRF Token to do a POST request to access an api and it requires a token to go through with the success, and the token is in the cookie, looks like this:
{'csrf_token': 'knjklfjg9g5yhbogbn98433y'}
How would I get just knjklfjg9g5yhbogbn98433y instead of the whole cookie?
You can turn a JSON string into a Python dictionary by using json.loads
import json
cookieStr = '{"csrf_token": "knjklfjg9g5yhbogbn98433y"}'
cookieDict = json.loads(cookieStr)
tokenValue = cookieDict["csrf_token"]

How to POST - API in thingspeak.comusing urllib in Python

I am working on a project where I have to get data from a website and then post it to a different website. At the moment I am still new, so I am using a thingspeak.com account to experiment on posting, and I am also following the same example used in the documentations of urllib, https://docs.python.org/2/library/urllib.html.
params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
# I am using this to check => eggs=2&bacon=0&spam=1
print params
f = urllib.urlopen("https://api.thingspeak.com/update?key=8TU6AC31T81MV52N&field1=",params)
print f.read()
However, when I check my thingspeak website http://api.thingspeak.com/channels/42628/feed.json?key=8TU6AC31T81MV52N, I will get this for that specific entry
{"created_at":"2015-06-17T10:05:12Z","entry_id":19,"field1":""}
Supposedly, or at least how I understood it, params should be posted to the website but I don't understand why I get the empty string. Also, it doesn't work if I loop it, it only works for the first iteration posting the empty string, and the rest are I will get 0 read from f.read(). What's the problem?! :\
All help is much appreciated. Also please correct if by I was mistaken.
You are sending the query parameter named field1 in the URL, but it is set to any empty string. Hence field1 is set to "" by thingspeak.com. Those values you pass in params are sent in the body of the HTTP POST request, they are not somehow appended to the URL.
You can set the field in one of two ways:
a GET request using:
f = urllib.urlopen("https://api.thingspeak.com/update?key=8TU6AC31T81MV52N&field1=my+value")
which includes the API key and a value for field1.
a POST request:
params = urllib.urlencode({'key': '8TU6AC31T81MV52N', 'field1': 'my value'})
f = urllib.urlopen("https://api.thingspeak.com/update", data=params)
thinkspeak will accept query parameters in the URL with a POST request, e.g. you can pass field1 in the URL and the API key in the body:
params = urllib.urlencode({'key': '8TU6AC31T81MV52N'})
f = urllib.urlopen("https://api.thingspeak.com/update?field1=hello", data=params)
However, playing around with the API it looks like it will only accept the query parameter named field1. All other fields are ignored, even those documented such as field2, field3, etc.

python 2.7 requests.get() returning cookie raising TypeError

I'm doing a simple HTTP requests authentication vs our internal server, getting the cookie back then hitting a Cassandra RESTful server to get data. The requests.get() chokes when returning the cookie.
I have a curl script that extracts the data successfully, I'd rather work with the response JSON data in pure python.
Any clues to what I've doing wrong below? I dump the cookie, it looks fine, very similar to my curl cookie.
Craig
import requests
import rtim
# this makes the auth and gets the cookie returned, save the cookie
myAuth = requests.get(rtim.rcas_auth_url, auth=(rtim.username, rtim.password),verify=False)
print myAuth.status_code
authCookie=myAuth.headers['set-cookie']
IXhost='xInternalHostName.com:9990'
mylink='http:/%s/v1/BONDISSUE?format=JSONARRAY&issue.isin=%s' % (IXhost, 'US3133XK4V44')
# chokes on next line .... doesn't like the Cookie format
r = requests.get(mylink, cookies=authCookie)
(Pdb) next
TypeError: 'string indices must be integers, not str'
I think the problem is on the last line:
r = requests.get(mylink, cookies=authCookie)
requests assumes that the cookies parameter is a dictionary, but you are passing a string object authCookie to it.
The exception raises when requests tries to treat the string authCookie as a dictionary.

Python requests module: urlencoding json data

I'm working on an API wrapper. The spec I'm trying to build to has the following request in it:
curl -H "Content-type:application/json" -X POST -d data='{"name":"Partner13", "email":"example#example.com"}' http://localhost:5000/
This request produces the following response from a little test server I setup to see exatly what headers/params etc are sent as. This little script produces:
uri: http://localhost:5000/,
method: POST,
api_key: None,
content_type: application/json,
params: None,
data: data={"name":"Partner13", "email":"example#example.com"}
So that above is the result I want my python script to create when it hits the little test script.
I'm using the python requests module, which is the most beautiful HTTP lib I have ever used. So here is my python code:
uri = "http://localhost:5000/"
headers = {'content-type': 'application/json' }
params = {}
data = {"name":"Partner13", "email":"example#exmaple.com"}
params["data"] = json.dumps(data)
r = requests.post(uri, data=params, headers=headers)
So simple enough stuff. Set the headers, and create a dictionary for the POST parameters. That dictionary has one entry called "data" which is the JSON string of the data I want to send to the server. Then I call the post. However, the result my little test script gives back is:
uri: http://localhost:5000/,
method: POST,
api_key: None,
content_type: application/json,
params: None,
data: data=%7B%22name%22%3A+%22Partner13%22%2C+%22email%22%3A+%22example%40example.com%22%7D
So essentially the json data I wanted to send under the data parameter has been urlendcoded.
Does anyone know how to fix this? I have looked through the requests documentation and cannot seem to find a way to not auto urlencode the send data.
Thanks very much,
Kevin
When creating the object for the data keyword, simply assign a variable the result of json.dumps(data).
Also, because HTTP POST can accept both url parameters as well as data in the body of the request, and because the requests.post function has a keyword argument named "params", it might be better to use a different variable name for readability. The requests docs use the variable name "payload", so thats what I use.
data = {"name":"Partner13", "email":"example#exmaple.com"}
payload = json.dumps(data)
r = requests.post(uri, data=payload, headers=headers)
Requests automatically URL encodes dictionaries passed as data here. John_GG's solution works because rather than posting a dictionary containing the JSON encoded string in the 'data' field it simply passes the JSON encoded string directly: strings are not automatically encoded. I can't say I understand the reason for this behaviour in Requests but regardless, it is what it is. There is no way to toggle this behaviour off that I can find.
Best of luck with it, Kevin.

Categories