I am trying to consume a RestAPI that I have already tested in C# but now I want to rewrite the Client in Python for learing effects. I am coding in Visual Studio under Windows.
What I did yet is:
import requests
class myClass:
def __init__(self, username, password):
self.username = username
self.password = password
def getToken(self):
endpoint = "https://test.com/web/service/auth/token"
headers = {
"username" : self.username,
"password" : self.password,
"environment" : "env_me",
"grant_type" : "password",
"Content_Type" : "application/x-www-form-urlencoded"
}
r = requests.post(endpoint, headers=headers)
return print(r.json())
myObj = myClass("UN","PS")
token = myObj.getToken()
print(token)
Running this code gives me the error:
SSLError(MaxRetryError('HTTPSConnectionPool(host=\'test.com\', port=443): Max retries exceeded with url: /web/service/auth/token (Caused by SSLError("Can\'t connect to HTTPS URL because the SSL module is not available."))'))
Since I could find any help for this I was trying to Import ssl but this gives me the error: The specific module could not be found. from ssl import ... gives me a whole bunch of stuff to choose but I do not know what to choose since I am new to Python. Could anyone help me get rid of the error?
Related
Set-up
I use the following Python code to log-in to a Adobe Commerce test environment via the Rest API,
import requests
host = 'https://b2b.test.163.com.pl'
store_code = 'PL_B2B_PL'
# Set the API endpoint for getting a customer token
endpoint = host + "/rest/" + store_code + "/V1/integration/customer/token"
# Set the credentials for the login request
credentials = {
"username": "myusername",
"password": "mypassword"
}
# Send a POST request to the login endpoint with the credentials
response = requests.post(endpoint, json=credentials, headers={"Content-Type": "application/json"})
# Check the response status code to see if the request was successful
if response.status_code == 200:
# Get the customer token from the response
customer_token = response.text
# Use the customer token in the Authorization header of subsequent API requests
headers = {
"Authorization": f"Bearer {customer_token}"
}
else:
# Handle the error response if the request was unsuccessful
print(f"Request failed: {response.text}")
Issue
Running the above code yields the following error,
ConnectionError: HTTPSConnectionPool(host='b2b.test.163.com.pl', port=443): Max retries exceeded with url: /rest/PL_B2B_PL/V1/integration/customer/token (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f7b718ed880>: Failed to establish a new connection: [Errno 60] Operation timed out'))
Question
How do I correctly connect to the test environment?
I think this code should've worked, but clearly I am wrong.
I'm using request in python to try and download this file:
http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11/N55W003.SRTMGL1.hgt.zip there are 14000 such files hence why I need to automate the process. The other techniques I've found online don't seem to work. I assume due the websites they are designed for using a different authentication method. I don't know much about web development so I can't work out how this authentication works.
Edit
This is the code:
import json
import requests
from requests.auth import HTTPBasicAuth
file = open("srtm30m_bounding_boxes.json", 'r')
strjson = file.read()
x = json.loads(strjson)
filenamelist = []
url = "http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11/N55W003.SRTMGL1.hgt.zip"
for i in range(14295):
filenamelist.append(x['features'][i]['properties']['dataFile'])
filenamelist[i] = "http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11/" + filenamelist[i]
jar = requests.cookies.RequestsCookieJar()
jar.set('urs_user_already_logged', 'yes')
jar.set('_urs-gui_session','8b972449036e60e3d83a6a819b93124d')
r = requests.get(url, cookies=jar)
And this is the error I get when I run the code:
ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
The simplest thing is to provide the username and password in the URL before the host, e.g.:
requests.get('http://{username}:{password}#e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11/{subpath}'.format(username=username, password=password, subpath=filenamelist[i]))
You can also supply the username/password as the auth parameter to get:
requests.get('http://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL1.003/2000.02.11/{subpath}'.format(subpath=filenamelist[i]), auth=(username, password))
totalhack is right that https is more secure, and it seems to work on this site. This form of authentication transmits the username and password as plaintext, so anyone who can observe the http request would also be able to steal your login. https encrypts the username / password since it encrypts the entire request.
I am trying to use Twilio in pythonanywhere and I know I need a proxy to make it work. My code looks like this:
class ProxiedTwilioHttpClient(HttpClient):
"""
General purpose HTTP Client for interacting with the Twilio API
"""
def request(self, method, url, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
session = Session()
session.verify = get_cert_file()
session.proxies = {
"https" : "https://52.14.161.178:3128"
}
request = Request(method.upper(), url, params=params, data=data, headers=headers, auth=auth)
prepped_request = session.prepare_request(request)
response = session.send(
prepped_request,
allow_redirects=allow_redirects,
timeout=timeout,
)
return Response(int(response.status_code), response.content.decode('utf-8'))
def send_sms(phone, content):
client = Client(api_key, api_secret, account_sid, http_client=ProxiedTwilioHttpClient())
message = client.messages.create(
to=phone,
from_="+19999999999", #of course I use the correct one
body=content)
return(message.sid)
But then it returns the following error:
.virtualenvs/sms/local/lib/python2.7/site-packages/requests/adapters.py",
line 502, in send raise ProxyError(e, request=request) requests.exceptions.ProxyError:
HTTPSConnectionPool(host='api.twilio.com', port=443):
Max retries exceeded with url: /2010-04-01/Accounts/XXXXXXXXX/Messages.json (Caused by ProxyError('Cannot connect to proxy.',
NewConnectionError('<urllib3.connection.Verif iedHTTPSConnection object at 0x7fa41a55e090>:
Failed to establish a new connection: [Errno 111] Connection refused',)))
I am using the following answer that seems to work for others: https://stackoverflow.com/a/43608637/7298530
How can I solve it?
You're specifying that your code should use a proxy at https://52.14.161.178:3128. That won't work on PythonAnywhere, you need to use the proxy that the service provides. To find out what address to use for that, start a Bash console and run
echo $http_proxy
[2018 edit] We now have a specific page on getting twilio to work with the pythonanywhere proxy
I created a simple web service and consumed it with pysimplesoap. Then I added ssl to the service(self signed) and tried to do the same but I am getting the error:
RuntimeError: Cannot determine service in WSDL: SOAP version: soap11
This is my code:
from pysimplesoap.client import SoapClient
import base64
import ssl
base64string = base64.encodestring('%s:%s' % ('username', 'password')).replace('\n', '')
ssl._create_default_https_context = ssl._create_unverified_context
authenticationHeader = {
"Authorization" : "Basic %s" % base64string,
}
client = SoapClient(wsdl="https://10.0.120.138/service.svc?wsdl",trace=True,http_headers=authenticationHeader)
response = client.method("param")
print response
Does anyone know why I am getting the error? I have a feeling I need to configure something..
This is not really an answer for the problem above but it is a solution..
I switched to zeep library and everything works now.
I'm having trouble getting my bot to login to a MediaWiki install on the intranet. I believe it is due to the http authentication protecting the wiki.
Facts:
The wiki root is: https://local.example.com/mywiki/
When visiting the wiki with a web browser, a popup comes up asking for enterprise credentials (I assume this is basic access authentication)
This is what I have in my user-config.py:
mylang = 'en'
family = 'mywiki'
usernames['mywiki']['en'] = u'Bot'
authenticate['local.example.com'] = ('user', 'pass')
This is what I have in mywiki_family.py:
# -*- coding: utf-8 -*-
import family, config
# The Wikimedia family that is known as mywiki
class Family(family.Family):
def __init__(self):
family.Family.__init__(self)
self.name = 'mywiki'
self.langs = { 'en' : 'local.example.com'}
def scriptpath(self, code):
return '/mywiki'
def version(self, code):
return '1.13.5'
def isPublic(self):
return False
def hostname(self, code):
return 'local.example.com'
def protocol(self, code):
return 'https'
def path(self, code):
return '/mywiki/index.php'
When I execute login.py -v -v, I get this:
urllib2.urlopen(urllib2.Request('https://local.example.com/w/index.php?title=Special:Userlogin&useskin=monobook&action=submit', wpSkipCookieCheck=1&wpPassword=XXXX&wpDomain=&wpRemember=1&wpLoginattempt=Aanmelden%20%26%20Inschrijven&wpName=Bot, {'Content-type': 'application/x-www-form-urlencoded', 'User-agent': 'PythonWikipediaBot/1.0'})):
(Redundant traceback info here)
urllib2.HTTPError: HTTP Error 401: Unauthorized
(I'm not sure why it has 'local.example.com/w' instead of '/mywiki'.)
I thought it might be trying to authenticate to example.com instead of example.com/wiki, so I changed the authenticate line to:
authenticate['local.example.com/mywiki'] = ('user', 'pass')
But then I get an HTTP 401.2 error back from IIS:
You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to accept.
Any help on how to get this working would be appreciated.
Update After fixing my family file, it now says:
Getting information for site mywiki:en
('http error', 401, 'Unauthorized', )
WARNING: Could not open 'https://local.example.com/mywiki/index.php?title=Non-existing_page&action=edit&useskin=monobook'. Maybe the server or your connection is down. Retrying in 1 minutes...
I looked at the HTTP headers on a plan urllib2.ulropen call and it's using WWW-Authenticate: Negotiate WWW-Authenticate: NTLM. I'm guessing urllib2 and thus pywikipedia don't support this?
Update Added a tasty bounty for help in getting this to work. I can authenticate using python-ntlm. How do I integrate this into pywikipedia?
Well the fact that login.py tries accessing '\w' instead of your path shows that there is a family configuration issue.
Your code is indented strangely: is scriptpath a member of the new Family class? as in:
class Family(family.Family):
def __init__(self):
family.Family.__init__(self)
self.name = 'mywiki'
self.langs = { 'en' : 'local.example.com'}
def scriptpath(self, code):
return '/mywiki'
def version(self, code):
return '1.13.5'
def isPublic(self):
return False
def hostname(self, code):
return 'local.example.com'
def protocol(self, code):
return 'https'
?
I believe that something is wrong with your family file. A good way to check is to do in a python console:
import wikipedia
site = wikipedia.getSite('en', 'mywiki')
print site.login_address()
as long as the relative address is wrong, showing '/w' instead of '/mywiki', it means that the family file is still not configured correctly, and that the bot won't work :)
Update: how to integrate ntlm in pywikipedia?
I just had a look at the basic example here. I would integrate the code before that line in login.py:
response = urllib2.urlopen(urllib2.Request(self.site.protocol() + '://' + self.site.hostname() + address, data, headers))
You want to write something of the like:
from ntlm import HTTPNtlmAuthHandler
user = 'DOMAIN\User'
password = "Password"
url = self.site.protocol() + '://' + self.site.hostname()
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, url, user, password)
# create the NTLM authentication handler
auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)
# create and install the opener
opener = urllib2.build_opener(auth_NTLM)
urllib2.install_opener(opener)
response = urllib2.urlopen(urllib2.Request(self.site.protocol() + '://' + self.site.hostname() + address, data, headers))
I would test this and integrate it directly into pywikipedia codebase if only I had an available ntlm setup...
Whatever happens, please do not vanish with your solution: we're interested, at pywikipedia, by your solution :)
I am guessing the problem you have is that the server expects basic authentication and you are not handling that in your client. Michael Foord wrote a good article about handling basic authentication in Python.
You did not provide enough information for me to be sure about this, so if that does not work, please provide some additional information, like network dump of you connection attempt.