get request failing in boto3 python 3.8 lambda - python-3.x

I am trying to write a lambda function in 3.8 version but I am getting error while doing a get requests
[ERROR] AttributeError: module 'botocore.vendored.requests' has no attribute 'get' Traceback (most recent call last): File "/var/task/lambda_function.py"
import json
from botocore.vendored import requests
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
print (request)
print(request['headers'])
token = request['headers']['cookie'][0]['value'].partition("=")[2]
print (token)
print(type(request['uri']))
consumer_id = request['uri'].rpartition('/')[-1]
print (consumer_id)
#Take the token and send it somewhere
token_response = requests.get(url = 'https://url/api/files/' + consumer_id, params = {'token': token})
print (token_response)
return request
I tried following this blog https://aws.amazon.com/blogs/compute/upcoming-changes-to-the-python-sdk-in-aws-lambda/
but not able to identify which layer to add. Could anyone please help

According to the link you provided and assuming that request was correctly installed you should be using
import requests
instead of
from botocore.vendored import requests

Related

request an API based on sql query

It´s muy first time developing an API. It's very simple. here is my code:
from flask import Flask, Response
from flask import request
from flask import jsonify
import pyodbc
from sqlalchemy import create_engine,Integer
import pandas as pd
import urllib
app = Flask(__name__)
params = urllib.parse.quote_plus("DRIVER={SQL Server Native Client 11.0};"
"SERVER=xxx.xx.x.x;"
"DATABASE=xxxxx;"
"UID=xxxx;"
"PWD=xxxx")
engine = create_engine('mssql+pymssql://xxxx:xxxx#xxx.xx.x.x/xxxx')
sql_talle = "RSCV_TALLE_PARA_CADA_MARCA.sql"
fd1 = open(sql_talle, 'r')
sqlFile1 = fd1.read()
fd1.close()
DF1 = pd.read_sql_query(sqlFile1,engine)
DF1.insert(14, 'PROVEEDOR', DF1.pop('PROVEEDOR'))
periodo=DF1['YEARMONTH_DATE'].drop_duplicates()
NIKE=DF1.loc[DF1['MARCA'] == 'NIKE']
NIKE=NIKE.to_dict('records')
#app.route('/NIKE',methods = ['GET'])
def show_codigo_Agrupador():
if request.method == 'GET':
response = jsonify({'NIKE':NIKE})
response.status_code = 200
return response
if __name__ == "__main__":
app.run(debug=True)
it´s working fine!
when I run the .py on a terminal I get that it´s Running on http://127.0.0.1:5000
After that I try to do a request on another .py, simulating an external user:
import requests
import json
url = 'http://127.0.0.1:5000/NIKE'
r=requests.get(url)
response=r.text
j=response.json()
print(j)
but I get this error:
Traceback (most recent call last):
File "c:\Users\mvazquez\DABRA\FLASK_API\prueba_request_api.py", line 7, in <module>
j=response.json()
AttributeError: 'str' object has no attribute 'json'
I have these questions:
what am I doing wrong here?
my data is based on an sql query, I need to run the script every day to have refresehed data or it is refreshed when request is done? (sorry if it's stupid, I have no idea about API)
thanks in advance!

AttributeError: module 'urllib3' has no attribute 'HTTPHeaderDict'

I am trying to send headers from lambda into an API.I have taken HTTPHeaderDict from https://urllib3.readthedocs.io/en/latest/user-guide.html .
import urllib3
import os
import json
# Get environment variable
api_url = os.getenv('API_URL')
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
request = json.loads(json.dumps(event))
print(json.dumps(request['headers']))
headers = request['headers']
request_headers = urllib3.HTTPHeaderDict()
for key in headers:
request_headers.add(key, headers[key])
http = urllib3.PoolManager()
response = http.request('GET', api_url + '/', headers=request_headers, timeout=10)
return {
'statusCode': response.status,
'headers': response.headers,
'body': response.data
}
I see the error in cloudwatch
[ERROR] AttributeError: module 'urllib3' has no attribute 'HTTPHeaderDict'
What version of urllib3 are you using? If you are using the latest pip installed package which is version 1.26.7 it won't have it exposed at the package import level. If you look at the docs for the latest stable release you'll see that it isn't mentioned as an import level Class.
The link you linked too is for 2.0.0dev0 version which you'll have to install from the github repo itself. If you can't install from the repo you should be able to access the HTTPHeaderDict class from the _collections module like from urllib3._collections import HTTPHeaderDict and then call it as request_headers = HTTPHeaderDict().
The HTTPHeaderDict seems to be not serializable and the error was in the way i was sending the response.
import urllib3
import os
import json
#from urllib3._collections import HTTPHeaderDict
# Get environment variable
api_url = os.getenv('API_URL')
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
request = json.loads(json.dumps(event))
http = urllib3.PoolManager()
response = http.request('GET', api_url + '/', headers=request['headers'], timeout=10)
response_headers = {}
for header_key in response.headers:
response_headers[header_key] = response.headers[header_key]
return {
'statusCode': response.status,
'headers' : response_headers,
'body': json.dumps('Hello from Lambda!')
}
I had to loop through the HTTPHeaderDict and put the value in another dictionary.As pointed by #mata request['headers'] can be used directly.
P.S I couldn't find aws docs that indicate which version of urllib3 is used for AWS Lambda functions

Invalid credentials when trying to connect to vTiger

I'm trying to log in via webservice within vtiger CRM5 with python
When putting my key and user name in params, I just get an INVALID_AUTH_TOKEN, but when putting it into body, I get INVALID_USER_CREDENTIALS. Which seems better but not quite working !
{'success': False, 'error': {'code': 'INVALID_USER_CREDENTIALS', 'message': 'Invalid username or password'}}
# -*- coding: utf-8 -*-
import json
import requests
from hashlib import md5
from requests.auth import HTTPBasicAuth
api_url_base = 'http://crmaddress/webservice.php'
username = 'myusername'
accessKey = 'fghdhgfhfdhgfd'
headers = {"ContentType":"application/x-www-form-urlencoded"}
response = requests.get(api_url_base,params={"operation":"getChallenge","username":username})
token = json.loads(response.content.decode('utf-8'))['result']['token']
key = md5(accessKey.encode('utf-8')+token.encode('utf-8')).hexdigest()
print(key)
response = requests.post(api_url_base,data={"operation":"login","accessKey":key,"username":username,},auth=HTTPBasicAuth('myusername','mypassword'),headers=headers)
print(json.loads(response.content.decode('utf-8')))
I cannot verify without running the code, but the problem seems to be somewhere along
key = md5(accessKey.encode('utf-8')+token.encode('utf-8')).hexdigest()
Also, instead of directly using the webservice, I would recommend creating a wrapper class. Please check out a python3 wrapper I wrote at github. Let me know if this helps.

How to debug an error of "'module' object is not callable"?

from picamera import PiCamera
import time
import json
import pybase64
import datetime
import requests
//CAPTURING A PICTURE AND SAVING IT//
camera = PiCamera()
camera.start_preview()
time.sleep(0.5)
camera.capture("/home/pi/Desktop/rasppi/images/image2.jpg")
camera.stop_preview()
//CONVERTING INTO BASE64 STRING//
with open("/home/pi/Desktop/rasppi/images/image2.jpg", "rb") as file:
string = pybase64.b64encode(file.read())
file.close()
url = "192.168.139.87:9000/upload"
payload = string
//USING POST REQUEST TO UPLOAD IMAGE ON URL//
response = requests('post', url, data = payload)
now = datetime.datetime.now()
time = str(now)
obj = json.loads(response.text)
id = ["emp_id"]
var = "Identified person is : " + id
print(var)
print(time)
It generates following error:
Traceback (most recent call last):
File "get_image.py", line 22, in <module>
response = requests('post', url, data = payload)
TypeError: 'module' object is not callable
This code deals with the program for capturing a picture with the help of raspberry pi and then POST it on the url. The POST request command shows some error.
You want:
response = requests.post(url, data=payload)

Unable to read the buffer from BytesIO in google app engine flex environment

Here is the related code
import logging
logging.getLogger('googleapicliet.discovery_cache').setLevel(logging.ERROR)
import datetime
import json
from flask import Flask, render_template, request
from flask import make_response
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from oauth2client.client import AccessTokenCredentials
...
#app.route('/callback_download')
def userselectioncallback_with_drive_api():
"""
Need to make it a background process
"""
logging.info("In download callback...")
code = request.args.get('code')
fileId = request.args.get('fileId')
logging.info("code %s", code)
logging.info("fileId %s", fileId)
credentials = AccessTokenCredentials(
code,
'flex-env/1.0')
http = httplib2.Http()
http_auth = credentials.authorize(http)
# Exports a Google Doc to the requested MIME type and returns the exported content. Please note that the exported content is limited to 10MB.
# v3 does not work? over quota?
drive_service = build('drive', 'v3', http=http_auth)
drive_request = drive_service.files().export(
fileId=fileId,
mimeType='application/pdf')
b = bytes()
fh = io.BytesIO(b)
downloader = MediaIoBaseDownload(fh, drive_request)
done = False
try:
while done is False:
status, done = downloader.next_chunk()
logging.log("Download %d%%.", int(status.progress() * 100))
except Exception as err:
logging.error(err)
logging.error(err.__class__)
response = make_response(fh.getbuffer())
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = \
'inline; filename=%s.pdf' % 'yourfilename'
return response
It is based on some code example of drive api. I am trying to export some files from google drive to pdf format.
The exception comes from the line
response = make_response(fh.getbuffer())
It throws the exception:
TypeError: 'memoryview' object is not callable
How can I retrieve the pdf content properly from the fh? Do I need to further apply some base 64 encoding?
My local runtime is python 3.4.3
I have used an incorrect API. I should do this instead:
response = make_response(fh.getvalue())

Resources