Is there any way to do HTTP PUT in python
I've used a variety of python HTTP libs in the past, and I've settled on requests as my favourite. Existing libs had pretty useable interfaces, but code can end up being a few lines too long for simple operations. A basic PUT in requests looks like:
payload = {'username': 'bob', 'email': 'bob@bob.com'}
>>> r = requests.put("http://somedomain.org/endpoint", data=payload)
You can then check the response status code with:
r.status_code
or the response with:
r.content
Requests has a lot synactic sugar and shortcuts that'll make your life easier.
HTTP PUT request in Python using JSON data
Your data
is already a JSON-formatted string. You can pass it directly to requests.put
instead of converting it with json.dumps
again.
Change:
response = requests.put(url, data=json.dumps(data), headers=headers)
to:
response = requests.put(url, data=data, headers=headers)
Alternatively, your data
can store a data structure instead, so that json.dumps
can convert it to JSON.
Change:
data = '[{"$key": 8},{"$key": 7}]'
to:
data = [{"$key": 8},{"$key": 7}]
How to specify python requests http put body?
Quoting from the docs
data – (optional) Dictionary or bytes to send in the body of the Request.
So this should work (not tested):
filepath = 'yourfilename.txt'
with open(filepath) as fh:
mydata = fh.read()
response = requests.put('https://api.elasticemail.com/attachments/upload',
data=mydata,
auth=('omer', 'b01ad0ce'),
headers={'content-type':'text/plain'},
params={'file': filepath}
)
How to correctly requests.put in Python 3.7
If you take a look at the API documentation
, you will notice it requires you to send required data into the body of the requests.
Here is an example on how to send data into the body using the requests module:
data = {
"message": yourMessageInfo,
"name": yourNameInfo,
"object": yourObjectInfo,
"priority": yourPriorityInfo,
"query": yourQueryInfo,
"tags": yourTagsInfo,
"type": yourTypeInfo
}
response = requests.put(api_url, headers=headers, json=data)
You will of course need to fill in all the information.
Another example straight from the documentation:
data = {
"message": "string",
"name": "string",
"options": {
"enable_logs_sample": false,
"escalation_message": "string",
"evaluation_delay": "integer",
"include_tags": false,
"locked": false,
"min_failure_duration": "integer",
"min_location_failed": "integer",
"new_host_delay": "integer",
"no_data_timeframe": "integer",
"notify_audit": false,
"notify_no_data": false,
"renotify_interval": "integer",
"require_full_window": false,
"restricted_roles": [],
"silenced": {
"<any-key>": "integer"
},
"synthetics_check_id": "string",
"threshold_windows": {
"recovery_window": "string",
"trigger_window": "string"
},
"thresholds": {
"critical": "number",
"critical_recovery": "number",
"ok": "number",
"unknown": "number",
"warning": "number",
"warning_recovery": "number"
},
"timeout_h": "integer"
},
"priority": "integer",
"query": "string",
"tags": [],
"type": "string"
}
response = requests.put(api_url, headers=headers, json=data)
More information in the API documentation
and the picture below:
request.put() but it request using GET by PUT on my python
You are almost certainly being redirected. The PUT request is sent, but the server responded with a 3xx redirection response code, which requests
then follows and issues a GET request for. I note that the path in your wireshark screenshot doesn't match the one used in your code (the /test
prefix is missing), further adding evidence that a redirection has taken place.
You can check the redirection history by looking at r.history
(each entry is another response object), or set allow_redirects=False
to not respond to redirects (you get the first response, nothing else).
You are probably getting redirected because you are double-encoding your JSON payload. There is no need to use json.dumps
on a string that is already a JSON document. You are sending a single JSON string, whose contents happen to be a JSON document. That is almost certainly the wrong thing to send.
Correct this by removing the json.dumps()
call, or by replacing the payload
string with a dictionary:
payload = {
"assignee": {
"district": "3",
"phone": "01010001000",
"carNum": "598865"
},
"deduction": {
"min": 1000,
"max": 2000
},
"meta": {
"unit-label": "1-1-1",
"year": "2017",
"quarter": "2"
}
}
Incidentally, you would be better off then using the json
keyword argument; you get the Content-Type: application/json
header as an added bonus:
headers = {"x-api-key": "test_api_dp" }
r = requests.put(url, json=payload, headers=headers)
Again, this assumes that payload
is a Python data structure, not a JSON document in a Python string.
PUT Request to REST API using Python
Syntax error in because of =
sign in your headers
dictionary:
headers = {'Authorization': 'Bearer ' + token, "Content-Type": "application/json", data=data}
It should be:
headers = {'Authorization': 'Bearer ' + token, "Content-Type": "application/json", 'data':data}
See data=data
is changed with 'data':data
. Colon and Single Quotes.
And are you sure you will be sending data in your headers? Or you should replace your payload
with data
in your put
request?
Edit:
As you have edited the question and now you are sending data as PUT request's body requests.put(data=data)
so there is no need of it in headers. Just change your headers to:
headers = {'Authorization': 'Bearer ' + token, "Content-Type": "application/json"}
But as you have set your Content-Type
header to application/json
so I think in your PUT request you should do
response = requests.put(url, data=json.dumps(data), headers=headers)
that is send your data as json.
python: HTTP PUT with binary data
It's because
data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.
from urllib2 doc
Handle the HTTP PUT method in Python WSGI
As I understand it, you will just want to read the stream environ['wsgi.input']
, because a PUT
request will send the entire contents of the PUT
as the body of the request.
I am not aware of any encoding issues you will have to deal with (other than the fact that it is binary).
Some time ago, I wrote a simple set of PHP scripts to take and give huge files from another server on a LAN. We started with POST, but quickly ran out of memory on the larger files. So we switched to PUT, where the PHP script could take it's good time looping through php://input
4096 bytes at a time (or whatever)... It works great.
Here is the PHP code:
$f1 = fopen('php://input', 'rb');
$f2 = fopen($FilePath, 'wb');
while($data = fread($f1, 4096))
{
fwrite($f2, $data);
}
fclose($f1);
fclose($f2);
From my experience in handling multipart/form-data
in WSGI with POST
, I have little doubt that you can handle a PUT
by just reading the input stream.
The python code should be like this:
output = open('/tmp/input', 'wb')
while True:
buf = environ['wsgi.input'].read(4096)
if len(buf) == 0:
break
output.write(buf)
Related Topics
Getting the Indices of Several Elements in a Numpy Array at Once
How to Copy Over an Excel Sheet to Another Workbook in Python
No Module Named 'Pandas._Libs.Tslibs.Timedeltas' in Pyinstaller
How to Make Custom Legend in Matplotlib
Overriding "+=" in Python? (_Iadd_() Method)
How to Add Timezone into a Naive Datetime Instance in Python
Convert Pandas Dataframe to a Nested Dict
How to Sort a List by Length of String Followed by Alphabetical Order
Identifying Objects, Why Does the Returned Value from Id(...) Change
Python Requests Ssl Error - Certificate Verify Failed
Conversion of Strings Like \\Uxxxx in Python
How to Give Column Name Dynamically from String Variable in SQL Alchemy Filter
How to Remove Duplicate Words in a String with Python
How to Open a Website with Urllib via Proxy in Python