how to parametrize url in put requests using python - python

I am trying to send parameterized url in put request using python.
One of my function "getipaddress()" is returning the device ip address as 192.168.72.31
Code:
import requests
ips= getipaddress()
URL = "https://%s/UDW/Command?entry=eprint.register" % ips
r = requests.put(url=URL,data=data, verify=False)
print r.status_code
Getting error : 405 error (Method Not Allowed response status code).

As per inputs from #Ami Hollander and #DeepSpace I have figured out that put request is not supported. Trying with get request, I am able to get the response
Code :
ips = getipaddress() # returns device ip:192.168.72.31
url = "https://%s/UDW/Command?entry=eprint.register" % ips
requests.get(url=URL,verify=False)
Output :
{
"state": 200,
"eprint_reg_state": "registering"
}

I guess your server doesn't accept PUT requests
in Flask : #app.route('/your_route', methods=['PUT'])
in Django : doesn't support PUT requests, you'll need to use http://www.django-rest-framework.org/

Related

Test GET and POST calls

I need to test POST and GET calls against an NGINX server.
I need to capture the error codes and verify the response. I was able to test the GET requests by hitting localhost:8080 (NGINX is running on docker exposing 8080), but I'm not sure how to test the POST calls.
Can we construct a dummy request and test POST call? NGINX runs with default page.
Below is one way to make a post request to an endpoint in python
import requests
API_ENDPOINT = "http://pastebin.com/api/api_post.php"
data = {param1:value1,
param2:value2}
#sending post request and saving response as response object
r = requests.post(url = API_ENDPOINT, data = data)
#extracting response text
pastebin_url = r.text
print("The pastebin URL is:%s"%pastebin_url)

Got 503 error code while retrieveing mediaid in wechat?

API http://admin.wechat.com/wiki/index.php?title=Transferring_Multimedia_Files
import requests
r='https://api.wechat.com/cgi-bin/token?grant_type=client_credential&appid=wx82c6ebdb6e33ad33&secret=c2861ec348b3c94087c4b64cbe166fbb' #credentials sharing no problem
a=(requests.get(r).json()['access_token'])
print(a)
params = (
('access_token', a),
('type', 'image'),
)
import os
files = {
'media': ('1.jpg', open('static/1.jpg', 'rb'),'image/jpg',),
}
print()
response = requests.post('http://file.api.wechat.com/cgi-bin/media/upload', params=params, files=files)
def uprint(x,file=None):
try:
pass
if x:
print(x.encode('cp65001',errors='backslashreplace').decode('cp1252'),file=file)
except Exception as e:
return f'{x}\n{e}'
def prin(*a):print(ascii(*a))
print(response.text,file=open('z.html','a',encoding="utf-8"))
print(response.headers)
Looks like you are using http for the upload call. I have seen this error returned from sites for this reason before.
The HTTP error 503 means "Service Unavailable". It is usually returned by a server when it is unable to handle the request due to a temporary overloading or maintenance of the server.
After checking the API documentation for wechat, I notided this:
This API must be used via HTTPS.
And then I noticed this in the Q&A:
Q: Which server should I send API requests to?
A: If you have an International Official Account, use api.wechat.com.
If you have a China Official Account, use api.weixin.qq.com.
So, in your case I think you need to use https, and the domain api.wechat.com, like this:
response = requests.post('https://api.wechat.com/cgi-bin/media/upload', params=params, files=files)

original IP getting detected by server when using python requests but not when using curl

I am trying to send a request to this URL https://verify-email.org/home/verify-as-guest/example#example.com via a proxy server.
I obtained the proxy server here:
https://free-proxy-list.net/
The verify-email site has a limit of 5 emails verified per hour for free.
When I use a proxy server, I can bypass this limit if I keep changing the proxy servers. This works when I use curl:
curl --proxy http://IP:PORT https://verify-email.org/home/verify-as-guest/example#example.com
The above command works perfectly.
However when I do the same thing in python:
import requests
from pprint import pprint
def check_email(email):
proxyDict = {
"http" : 'http://IP:PORT'
}
result = requests.get('https://verify-email.org/home/verify-as-guest/' + email, proxies=proxyDict, timeout=5).json()
pprint(result)
check_email('example#example.com')
It doesn't work. It just gives me 5 tries and then stops working even if I change the IP which leads me to believe that there is a difference in the request sent by curl and the request sent by requests.
Is there any way I can get the same "curl" request in python-requests?
The proxyDict only contains a proxy to use for insecure http requests, but the service is using https.
Try
proxyDict = {
"http" : 'http://IP:PORT',
"https" : 'http://IP:PORT',
}

Microsoft Dynamics CRM 2016 Web API Put request clears value

I'm trying to use a put request to update Dynamics CRM. When I run the following python code I get a 204 response, but instead of updating a value it clears it. For example firstname gets updated to null instead of "WebApiUpdate".
import adal
import json
import urllib2
import requests
endpoint = "https://login.microsoftonline.com/00000000-0000-0000-0000-000000000002"
username = "example#example.com"
password = "password"
resource_uri = "https://orgname.crm.dynamics.com"
token_response = adal.acquire_token_with_username_password(endpoint,username,password,resource= resource_uri)
print token_response['accessToken']
payload = { "value": "WebApiUpdate"}
url = "http://xxxxx.crm.dynamics.com/api/data/v8.0/contacts(00000000-0000-0000-0000-000000000001)/firstname"
headers = {"Authorization":"Bearer "+token_response['accessToken']}
r = requests.put(url,data=payload,headers=headers)
print r.content
Solution:
set the url to be https:// instead of http://
set data = payload to json = payload in the request. ex:
r = requests.put(url,json=payload,headers=headers)
What was going wrong:
The initial call, which included the payload (regardless of if it was set to data or json), received a response of HTTP/1.0 301 Moved Permanently. In this response was a header with the new location. This location simply included https:// in the url. Then my code sent out a second put request that went to the correct https url, had the correct header parameters, but did not include the payload. This caused my put request to not include the value to update to, so Microsoft Dynamics CRM set the value to null.
Microsoft Dynamics CRM requires the put request payload to be formatted in json. After I updated the link to be https:// and the payload was included, it was formatted as x-www-form-urlencoded.That means the payload was appended to the request as value=WebApiUpdate. This caused a reply of HTTP/1.1 400 Bad Request. Changing the payload to be formatted as json means the payload will be appended to the request as {"value": "WebApiUpdate"}.
How I solved it:
I set my program to output the http put call it was making by adding the below code that I found from this stack overflow question. I then noticed that there were two non identical put calls and went from there.
import logging
try:
import http.client as http_client
except ImportError:
# Python 2
import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
I read the documentation on the request method here which I found on this stack overflow question

Infoblox WAPI: how to search for an IP

Our network team uses InfoBlox to store information about IP ranges (Location, Country, etc.)
There is an API available but Infoblox's documentation and examples are not very practical.
I would like to search via the API for details about an IP. To start with - I would be happy to get anything back from the server. I modified the only example I found
import requests
import json
url = "https://10.6.75.98/wapi/v1.0/"
object_type = "network"
search_string = {'network':'10.233.84.0/22'}
response = requests.get(url + object_type, verify=False,
data=json.dumps(search_string), auth=('adminname', 'adminpass'))
print "status code: ", response.status_code
print response.text
which returns an error 400
status code: 400
{ "Error": "AdmConProtoError: Invalid input: '{\"network\": \"10.233.84.0/22\"}'",
"code": "Client.Ibap.Proto",
"text": "Invalid input: '{\"network\": \"10.233.84.0/22\"}'"
}
I would appreciate any pointers from someone who managed to get this API to work with Python.
UPDATE: Following up on the solution, below is a piece of code (it works but it is not nice, streamlined, does not perfectly checks for errors, etc.) if someone one day would have a need to do the same as I did.
def ip2site(myip): # argument is an IP we want to know the localization of (in extensible_attributes)
baseurl = "https://the_infoblox_address/wapi/v1.0/"
# first we get the network this IP is in
r = requests.get(baseurl+"ipv4address?ip_address="+myip, auth=('youruser', 'yourpassword'), verify=False)
j = simplejson.loads(r.content)
# if the IP is not in any network an error message is dumped, including among others a key 'code'
if 'code' not in j:
mynetwork = j[0]['network']
# now we get the extended atributes for that network
r = requests.get(baseurl+"network?network="+mynetwork+"&_return_fields=extensible_attributes", auth=('youruser', 'youpassword'), verify=False)
j = simplejson.loads(r.content)
location = j[0]['extensible_attributes']['Location']
ipdict[myip] = location
return location
else:
return "ERROR_IP_NOT_MAPPED_TO_SITE"
By using requests.get and json.dumps, aren't you sending a GET request while adding JSON to the query string? Essentially, doing a
GET https://10.6.75.98/wapi/v1.0/network?{\"network\": \"10.233.84.0/22\"}
I've been using the WebAPI with Perl, not Python, but if that is the way your code is trying to do things, it will probably not work very well. To send JSON to the server, do a POST and add a '_method' argument with 'GET' as the value:
POST https://10.6.75.98/wapi/v1.0/network
Content: {
"_method": "GET",
"network": "10.233.84.0/22"
}
Content-Type: application/json
Or, don't send JSON to the server and send
GET https://10.6.75.98/wapi/v1.0/network?network=10.233.84.0/22
which I am guessing you will achieve by dropping the json.dumps from your code and handing search_string to requests.get directly.

Categories