AWS Lambda deployment issue using zappa - python-3.x

I'm using tensorflow and ImageAI in my python code, but when trying to upload it on Lambda getting following warning:
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.
It's successfull and working when I removed this line from my code:
from imageai.Prediction.Custom import CustomImagePrediction
I have created virtual environment and uploaded package on lambda using zappa, but no success
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/')
def hello_world():
from imageai.Prediction.Custom import CustomImagePrediction
import os
filename = 'Image path'
prediction = CustomImagePrediction()
prediction.setModelTypeAsResNet()
prediction.setModelPath("Model path")
prediction.setJsonPath("Model json path")
prediction.loadModel(num_objects=7)
predictions, probabilities = prediction.predictImage(filename, result_count=3)
data = {}
for eachPrediction, eachProbability in zip(predictions, probabilities):
data[eachPrediction] = eachProbability
return jsonify({"status":"200","message": "Ok"})
if __name__ == '__main__':
app.run(threaded=False)
Expected Result: Your updated Zappa deployment is live!:
https://i8ppr4snid.execute-api.us-east-1.amazonaws.com/
Actual Result: Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.

Related

How do I solve page not found error in flask rest api

I have developed a flask application that returns some text from OPEN-AI by giving some inputs.
But unfortunately the rest API in my application returns 404 error.
Here is the code:
from crypt import methods
from warnings import catch_warnings
from flask import Flask,request
from flask_cors import CORS
import flask
import openai
from flask_restful import Api,Resource
import base64
import json
#Init
app = Flask(__name__)
CORS(app)
api = Api(app)
app.run(host='0.0.0.0',port=8080)
#OPENAI CREDENTIALS
openai.api_key = ""
#Functions
class advert(Resource):
def post(self):
try:
request_body=request.json
A=request_body["data"]
adprompt = "Write an advertisement for " + A
response = openai.Completion.create(
engine="text-davinci-002",
prompt=adprompt,
temperature=0.7,
max_tokens=70,
top_p=1.0,
n=1
)
json_advert = json.loads(str(response))
advert_output = json_advert['choices'][0]['text']
to_return= json_advert = json.loads(str(advert_output))
return to_return,200
except:
return ({"ERROR":"Error Occured"}),500
#Mapping
api.add_resource(advert,'/data',methods=['POST'])
if __name__=='__main__':
app.run(debug=True)
This is the response i get:
192.168.1.21 - - [24/Nov/2022 11:52:59] "POST /data HTTP/1.1" 404 -
I've tried changing the port and endpoints, nothing helped .
How to solve this.
Your problem is at this line,
app.run(host='0.0.0.0',port=8080)
take it out, then add the parameters into the last line,
if __name__=='__main__':
app.run(debug=True, host='0.0.0.0',port=8080)
A bit more explanation, when the code hits app.run, it actually starts the server and not running the line api.add_resource. Hence, no path was configured.

How to return 401 in flask despite authorization

I am new to flask and I want to return 401 error, I am not using authentication, I am simply using a parameter api_key to check whether the user is authenticated.
I've tried abort(401) and return false, but it returns error 400 'Bad Request', is this the default way it returns a 401. Or is there a different way to do this?
My Code:
import flask
from flask import jsonify, request, Response
from flask_cors import CORS, cross_origin
from GoogleNews import GoogleNews
googlenews = GoogleNews()
googlenews.set_lang('en')
googlenews.set_period('1d')
googlenews.set_encode('utf-8')
app=flask.Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#cross_origin()
#app.route('/', methods=["GET"])
def return_news():
API_KEY = request.args['api_key']
if API_KEY == "xyz":
googlenews.get_news('TECHNOLOGY')
return jsonify(googlenews.result(True)[0:4])
else:
return Response(response="Unauthorized", status=401)
Thankyou
instead, try flask.Response object.
from flask import Flask, Response
app = Flask(__name__)
#app.route("/abort")
def abort():
return Response(response="Unauthorized", status=401)
app.run()
without the actual code it is hard to tell, but I think it is not using the flask abort() but the python internal abort() function.
Check the code below:
import flask
app = flask.Flask("aborter")
#app.route("/abort")
def abort():
return flask.abort(401)
if __name__ == '__main__':
app.run()
Happy Coding

get request failing in boto3 python 3.8 lambda

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

Cathing flask abort status code within a test_request_context

I want to understand how I can catch an HTTPException raised by flask.abort while using a test_request_context in a test for the calling method only.
# example.py
import flask
#api.route('/', methods=['POST'])
def do_stuff():
param_a = get_param()
return jsonify(a=param_a)
# check if request is json, return http error codes otherwise
def get_param():
if flask.request.is_json():
try:
data = flask.request.get_json()
a = data('param_a')
except(ValueError):
abort(400)
else:
abort(405)
# test_example.py
from app import app # where app = Flask(__name__)
from example import get_param
import flask
def test_get_param(app):
with app.test_request_context('/', data=flask.json.dumps(good_json), content_type='application/json'):
assert a == get_param()
In the get_param method above, I try to abort if the is_json() or the get_json() fail. To test this, I pass test_request_context without a content_type and, based on this blog and this answer, I tried adding a nested context manager like so:
# test_example.py
from app import app # where app = Flask(__name__)
from example import get_param
from werkzeug.exceptions import HTTPException
import flask
def test_get_param_aborts(app):
with app.test_request_context('/', data=flask.json.dumps('http://example', 'nope'), content_type=''):
with pytest.raises(HTTPException) as httperror:
get_param()
assert 405 == httperror
but I get a assert 405 == <ExceptionInfo for raises contextmanager> assertion error.
Can someone please explain this and suggest a way to test the abort in this get_param method?
Update:
Based on #tmt's answer, I modified the test. However, even though the test passes, while debugging I notice that the two assertions are never reached!
# test_example.py
from app import app # where app = Flask(__name__)
from example import get_param
from werkzeug.exceptions import HTTPException
import flask
def test_get_param_aborts(app):
with app.test_request_context('/', data=flask.json.dumps('http://example', 'nope'), content_type=''):
with pytest.raises(HTTPException) as httperror:
get_param() # <-- this line is reached
assert 405 == httperror.value.code
assert 1 ==2
httperror is an instance of ExceptionInfo which is pytest's own class that describes the exception. Once it happens, httperror would also contain value property which would be the instance of the HTTPException itself. If my memory is correct HTTPException contains code property that equals to the HTTP status code so you can use it to do the assertion:
# test_example.py
from app import app
from example import get_param
from werkzeug.exceptions import HTTPException
import flask
def test_get_param_aborts(app):
with app.test_request_context('/', data=flask.json.dumps(), content_type=''):
with pytest.raises(HTTPException) as httperror:
get_param()
assert 405 == httperror.value.code
Notes:
get_param() needs to be called within pytest.raises() context manager.
The assertion needs to be done outside of the context manager because once an exception is raised the context ends.
I don't know if pytest.raise is your typo or if it really existed in older versions of pytest. AFAIK it should be pytest.raises.

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