I have an example of curl request:
curl -X UNLINK
-H "Authorization: OAuth <>" -H 'Link: <https://some/my/url>; rel="relates"' "https://some/my/url"
I have already converted curl request with parameter -X LINK to SESSION.patch(...):
headers = {
'Content-Type': 'application/json',
'Authorization': 'OAuth %s' % some_token
}
params = (
('notify', 'False'),
)
data = '{"links":[{"relationship":"relates", "key":"some_key", "origin":"some_url"}]}'
r = SESSION.patch('https://some/url, params=params, data=data)
But I how to implement -X UNLINK using requests?
As far as I know there is no method in requests.Session() like unlink()and .delete() is not allowed by API.
You can pass in custom verbs with the request() method:
SESSION.request('UNLINK', url, ...)
See the Custom verbs section of the Advanced section of the requests documentation.
The default methods like .get(), .post() and .patch(), are all just wrappers for .request(), explicitly setting the verb.
Related
I am using FastAPI to serve some ML models and I have a Streamlit basic UI using Python Requests module.
One of my service is getting an image through a POST request and it is working like a charm.
Server side
#app.post("/segformer")
async def segformer(file: Optional[UploadFile] = None):
curl given by {BASE_URI}/docs
curl -X 'POST' \
'http://localhost:8080/segformer' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#image1.jpg;type=image/jpeg'
Client side using Python Requests
response = requests.post(f"{BASE_URI}/segformer", files=files)
As soon as I want to add additional parameters, it gets creepy. For example:
Server side
#dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = Query(...)
#app.post("/detr")
async def detr(file: UploadFile = File(...), model: ModelInterface = Depends()):
curl -- given by {BASE_URI}/docs
curl -X 'POST' \
'http://localhost:8080/detr?model_name=detr&tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#image1.jpg;type=image/jpeg'
Until that point everything works fine. Once I want to convert that call using Python Requests, I have some issues, which always end up in /detr HTTP/1.1" 400 Bad Request error.
Here is what I've tried:
Client side using Python Requests
headers = {
"Content-type": "multipart/form-data",
"accept": "application/json"
}
payload = {
"tags": ["balloon", "dog"]
}
response = requests.post(
f"{BASE_URI}/detr",
headers=headers,
json=payload, <- also *data*
files=files,
)
At the end it seems that the problem narrows on how to convert this:
curl -X 'POST' \
'http://localhost:8080/detr?tags=balloon&tags=dog' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#image1.jpg;type=image/jpeg'
to a valid Python Requests call!
I also faced the issue that the following FastAPI code:
#dataclass
class ModelInterface:
model_name: str = "detr"
tags: List[str] = None
#app.post("/detr2")
async def detr2(file: UploadFile = File(...), model: ModelInterface = Form(...)):
...
translates to this curl command:
curl -X 'POST' \
'http://localhost:8080/detr2' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#image1.jpg;type=image/jpeg' \
-F 'model={
"model_name": "detr",
"tags": [
"balloon", "dog"
]
}'
which fails with a "POST /detr2 HTTP/1.1" 422 Unprocessable Entity error
To pass query parameters in Python requests, you should use params key instead. Hence:
response = requests.post(url='<your_url_here>', params=payload)
Additionally, there is no need to set the Content-type in the headers, as it will automatically be added, based on the parameters you pass to requests.post(). Doing so, the request will fail, as, in addition to multipart/form-data,"Content-type must include the boundary value used to delineate the parts in the post body. Not setting the Content-Type header ensures that requests sets it to the correct value" (ref). Have a look at this and this. Also, make sure that in files you use the same key name you gave in your endpoint, i.e., file. Thus, in Python requests it should look something like the below:
files = {('file', open('my_file.txt', 'rb'))}
response = requests.post(url='<your_url_here>', files=files, params=payload)
You could also find more options as to how to send additional data along with files at this answer.
I've been trying to connect to an oauth2 API. I've managed to write a code that delivers a token, so the token is not a problem.
I've checked that with curl. The following works:
curl -X GET \
https://api.website.pl/sale/delivery-methods \
-H 'Authorization: Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA' \
-H 'accept: application/vnd.website.public.v1+json'
<- This returns the data I need.
However, I simply can't make it work in python.
headers = {}
headers['Authorization'] = 'Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA'
headers['Accept'] = 'application/vnd.website.public.v1+json'
get_url = 'https://api.website.pl/sale/delivery-methods'
requests.get(get_url, headers)
The response is <Response [406]>, incorrect data, which I'm interpreting as a signal I didn't pass all the relevant authorization headers.
Any ideas how to fix that?
try this:
headers = {}
headers['Authorization'] = 'Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA'
headers['Accept'] = 'application/vnd.website.public.v1+json'
get_url = 'https://api.website.pl/sale/delivery-methods'
response = requests.get(get_url, headers=headers)
I have the following format for request headers:
{
"projectName": New001,
"cloudRegions":{"REGION1":"centralus"},
"cloudAccountName":"XXX-XXXX-XXXX"
}
How do I format this to accept the {"REGION1":"centralus"}?
My Python code:
url = 'www.myexample.com'
headers = {'Content-Type': 'application/json',
'projectName': New001,
'cloudRegions':{'REGION1':'centralus'},
'cloudAccountName':'XXX-XXXX-XXXX'
}
r = requests.post(url, headers=headers)
The problem is I can't make the request to where cloudRegions will be formatted correctly. The value is in dictionary format but it doesn't like that. I've tried wrapping it in str(), using json.loads(), json.dumps(), but it always ends up formatted wrong. How do I format it to be an object that will be accepted as a pair?
This CURL works, and you will see the same format:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"projectName": "New001", \
"cloudRegions":{"REGION1":"centralus"}, \
"cloudAccountName":"XXX-XXXX-XXXX" \
}' 'http://www.myexample.com'
You are using HTTP headers to send your data (which is very unusual), while your curl example clearly shows that you must send the data in HTTP body, formatted as JSON. requests can do that very easily.
So simply use:
url = 'www.myexample.com'
data = {'projectName': 'New001',
'cloudRegions': {'REGION1':'centralus'},
'cloudAccountName': 'XXX-XXXX-XXXX'
}
r = requests.post(url, json=data)
I have this curl command and I would like to know if I have converted it correctly to pycurl.
curl command
curl -D- -u fred:fred -X PUT --data{see below} -H "Content-Type:application/json" http://kelpie9:8081/rest/api/2/issue/QA-31
{
"fields":
{
"assignee":{"name":"harry"}
}
}
python code
def assign(self, key, name):
data = json.dumps({"fields":{"assignee":{"name":name}}})
c= pycurl.Curl()
c.setopt(pycurl.VERBOSE, 1)
c.setopt(pycurl.URL, "http://xxx/rest/api/2/issue/"+ key )
c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json'])
c.setopt(pycurl.USERPWD, "****")
c.setopt(pycurl.PUT, 1)
c.setopt(pycurl.POSTFIELDS,data)
c.perform(
Nopes. First off: use curl's --libcurl option to get a first template.
Then, "-X PUT" translates to CUSTOMREQUEST set to "PUT", only changing the actual method keyword.
I would personally accomplish this by using the remarkable requests library
import requests
import requests.auth
import json
def assign(key, name):
url = "http://xxx/rest/api/2/issue/" + key
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
data = json.dumps({"fields": {"assignee": {"name": name}}})
r = requests.put(url, data=data, headers=headers, auth=requests.auth.HTTPBasicAuth('fred', 'fred'))
print(r.status_code)
print(r.json())
curl -j --libcurl git.txt -D- -u fred:fred -X PUT --data"{\"fields\":{\"assignee\":{\"name\":\"FRED\"}}}" -H "Content-Type:application/json" http://kelpie9:8081/rest/api/2/issue/QA-31
this gives the template in git.txt .
Also in the data field the inner quotes must be escaped as shown above.
The working code is attached below.
def assign(self, key, name):
self._startCurl()
self.c.setopt(pycurl.URL, "http://xxx/rest/api/2/issue/"+ key )
self.c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json'])
self.c.setopt(pycurl.USERPWD, "fred:fred")
self.c.setopt(pycurl.CUSTOMREQUEST, "PUT")
data = json.dumps({"fields":{"assignee":{"name":name}}})
self.c.setopt(pycurl.POSTFIELDS,data)
self.c.perform()
self.c.close()
Thanks to Daniel Stenberg for pointing it out
I am trying to use the toggl api.
I use Requests instead of Urllib2 for doing my GETs en POSTS. But i am stuck.
payload = {
"project":{
"name":"Another Project",
"billable":False,
"workspace":{
"Name":"jorrebor's workspace",
"id":213272
},
"automatically_calculate_estimated_workhours":False
}
}
url = "https://www.toggl.com/api/v6/projects.json"
r = requests.post(url, data=json.dumps(payload), auth=HTTPBasicAuth('j_xxxxx#gmail.com', 'mypassword'))
Authentication seems to be fine, but the payload format probably isn't.
a curl command with the same parameters:
curl -v -u heremytoken:api_token -H "Content-type: application/json" -d "{\"project\":{\"billable\":true,\"workspace\":{\"id\":213272},\"name\":\"Another project\",\"automatically_calculate_estimated_workhours\":false}}" -X POST https://www.toggl.com/api/v6/projects.json
does work fine.
What wrong with my payload? The response is get is:
["Name can't be blank","Workspace can't be blank"]
which leads me to conclude that the authentication works but toggl cannot read my json object.
Seems like you should try setting the header to a JSON application, rather than the default format, and send a JSON object instead of the Python dict. Check it out here:
payload = {"project":{"name":"Another Project",
"billable":False,
"workspace":{"Name":"jorrebor's workspace",
"id":213272},
"automatically_calculate_estimated_workhours":False
} }
parameters_json = json.dumps(payload)
headers = {'Content-Type': 'application/json')
r = client.post(url, data=parameters_json, headers=headers)
which should allow the site to read the json object just fine.