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
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 want to integrate a webhook in my Django application that supports only HTTPS requests. I want to test in my local machine so here I am using ngrok to make my localhost HTTPS i.e. https://c71e-2415-201-138f-ad9d-3005-825a-23c9-c788.ngrok.io/
and my local URL is
http://localhost:8000
I created a URL in my application named call_webhook_internally and related views.py function is
#csrf_exempt
def call_webhook_internally(request):
try:
ng_rok_url = https://c71e-2415-201-138f-ad9d-3005-825a-23c9-c788.ngrok.io/
url = ng_rok_url + "call_webhook/"
headers = {
"Timestamp": str(datetime.utcnow()),
}
payload = json.loads(request.body)
response = requests.request("POST", url, headers=headers, data=payload)
return HttpResponse("success")
except Exception as e:
return HttpResponse("Error")
the upper function is calling and when my request is called to call webhook using python it blocks the main thread and postman goes in an infinite loop, in ngrok terminal I am getting that request is received but in function, my print statement is not printing. I want to call my internal webhook in my existing app views.py function is call_webhook i.e.
def call_webhook_internally(request):
print(request)
return HttpResponse("webhook_called")
After 10-15 minutes getting error i.e.
webhook failed. Error HTTPSConnectionPool(host='c10e-2105-215-138f-ad9d-3005-825a-23c9-c788.ngrok.io',
port=443): Max retries exceeded with url: /call_webhook/ (Caused by SSLError(SSLError("read error:
Error([('SSL routines', 'ssl3_get_record', 'decryption failed or bad record mac')],)",),))
so pls suggest to me some way to do this is am I doing something wrong?
Thanks
I am trying to post test_data output from below python script (abc.py) to telegraf over http_listener_v2.
abc.py
------
import requests
url = "https://testazure.local/telegraf"
test_data = {'key1': 'value1'}
op = requests.post(url, data = test_data)
print(op.test_data)
Here is the snippets from my telegraf.conf file for inputs .
telegraf.conf
-----------------
[[inputs.http_listener_v2]]
# ## Address and port to host HTTP listener on
# methods = ["POST", "PUT"]
data_format = "json"
Not sure , if i am passing all the requsite details to the input plugin .
Getting connection error in an attempt to execute my python script . Any advise /help would be highly appreciated .
Traceback (most recent call last):
File "abc.py", line 6, in <module>
x = requests.post(url, data = test_data)
File "/usr/local/lib/python3.6/site-packages/requests/api.py", line 119, in post
return request('post', url, data=data, json=json, **kwargs)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host'testazure.local', port=443):
Max retries exceeded with url: /telegraf (Caused by
NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f9eb8c72438>:
Failed to establish a new connection: [Errno 111] Connection refused',))
I think your url needs http and not https. I have this exact setup and I am looking for an answer as well.
Actually seeing your question, I was able to solve my problem. I had the following code... notice the post method arguments... json
host = "rpi4-2GB"
port = 8080
path = "/telegraf"
weather_dict = data
url_str = "http://{}:{}{}".format(host, port, path)
http_res = requests.post(url=url_str, json=dumps(weather_dict))
>>> http_res.status_code
400
after reading your question here, I changed my kwarg to data
url_str = "http://{}:{}{}".format(host, port, path)
http_res = requests.post(url=url_str, data=dumps(weather_dict))
>>> http_res.status_code
204
204 is the proper value to get back from my experience with telegraph's http_listener_v2 plugin.
PYTHON
import requests
url = "https://REDACTED/pb/s/api/auth/login"
r = requests.post(
url,
data = {
'username': 'username',
'password': 'password'
}
)
NIM
import httpclient, json
let client = newHttpClient()
client.headers = newHttpHeaders({ "Content-Type": "application/json" })
let body = %*{
"username": "username",
"password": "password"
}
let resp = client.request("https://REDACTED.com/pb/s/api/auth/login", httpMethod = httpPOST, body = $body)
echo resp.body
I'm calling an API to get some data. Running the python code I get the traceback below. However, the nim code works perfectly so there must be something wrong with the python code or setup.
I'm running Python version 2.7.15.
requests lib version 2.19.1
Traceback (most recent call last):
File "C:/Python27/testht.py", line 21, in <module>
"Referer": "https://REDACTED.com/pb/a/"
File "C:\Python27\lib\site-packages\requests\api.py", line 112, in post
return request('post', url, data=data, json=json, **kwargs)
File "C:\Python27\lib\site-packages\requests\api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 512, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 622, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests\adapters.py", line 511, in send
raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='REDACTED.com', port=443): Max retries exceeded with url: /pb/s/api/auth/login (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)'),))
The requests module will verify the cert it gets from the server, much like a browser would. Rather than being able to click through and say "add exception" like you would in your browser, requests will raise that exception.
There's a way around it though: try adding verify=False to your post call.
However, the nim code works perfectly so there must be something wrong with the python code or setup.
Actually, your Python code or setup is less to blame but instead the nim code or better the defaults on the httpclient library. In the documentation for nim can be seen that httpclient.request uses a SSL context returned by getDefaultSSL by default which according to this code creates a context which does not verify the certificate:
proc getDefaultSSL(): SSLContext =
result = defaultSslContext
when defined(ssl):
if result == nil:
defaultSSLContext = newContext(verifyMode = CVerifyNone)
Your Python code instead attempts to properly verify the certificate since the requests library does this by default. And it fails to verify the certificate because something is wrong - either with your setup or the server.
It is unclear who has issued the certificate for your site but if it is not in your default CA store you can use the verify argument of requests to specify the issuer CA. See this documentation for details.
If the site you are trying to access works with the browser but fails with your program it might be that it uses a special CA which was added as trusted to the browser (like a company certificate). Browsers and Python use different trust stores so this added certificate needs to be added to Python or at least to your program as trusted too. It might also be that the setup of the server has problems. Browsers can sometimes work around problems like a missing intermediate certificate but Python doesn't. In case of a public accessible site you could use SSLLabs to check what's wrong.
There is two tries to get response from "working" django server. Working version is hardcoded and not working while unittesting
# working
# a = requests.post('http://localhost:8000/ImportKeys/',
# data=json.dumps({'user_id': key_obj.email,
#'key': self.restore_pubkey(key_obj.fingerprint)}))
# not working
a = requests.post('http://' + request.get_host() + reverse('import_keys'),data=json.dumps({'user_id': key_obj.email,'key': self.restore_pubkey(key_obj.fingerprint)}))
On that version, that I whant to starts working, I've got this(end stacktrace):
File "/home/PycharmProjects/lib/python3.4/site-packages/requests/sessions.py", line 576, in send
r = adapter.send(request, **kwargs)
File "/home/PycharmProjects/lib/python3.4/site-packages/requests/adapters.py", line 437, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='testserver', port=80): Max retries exceeded with url: /ImportKeys/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known',))
And yes, I see that it's trying connect to 80 port, and this is bad.
To test your views in the TestCase classes, use django.test.Client, which is designed specifically for that purpose. If you inherit your test cases from django.test.TestCase, it's already available via the self.client attribute.
class YourTestCase(TestCase):
def test_import_keys_posting(self):
data = {
'user_id': key_obj.email,
'key': self.restore_pubkey(key_obj.fingerprint)
}
response = self.client.post(reverse('import_keys'), data)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), {'result': 'ok'})
And if you use Django Rest Framework, consider using its wonderful APIClient, which simplifies API testing even more.
If you need to send requests to the server during tests (in that case this will probably not be from the test code itself but from some mock or from JS code):
Extend LiveServerTestCase instead TestCase. This will launch an actual server during tests.
If you are using request.build_absolute_uri() in your regular code which is being tested, you need to change the test code to update the HTTP request headers accordingly like this:
checkout_url = '{}{}'.format(self.live_server_url, reverse('checkout', kwargs={'pk': article.id}))
parsed_url = parse.urlparse(self.live_server_url)
# add the info on host and port to the http header to make subsequent
# request.build_absolute_uri() calls work
response = self.client.get(checkout_url, SERVER_NAME=parsed_url.hostname, SERVER_PORT=parsed_url.port)