Flask 400 Bad request KeyError - python

My code for the flask server is this,
from flask import Flask, request
app = Flask(__name__)
todos = {}
#app.route('/<todo_id>', methods=['GET', 'PUT', 'DELETE'])
def main(todo_id):
if request.method == 'GET':
try:
return {todo_id: todos[todo_id]}
except:
return {"status": "paused or off"}
elif request.method == 'DELETE':
if todo_id in todos:
del todos[todo_id]
return '', 204
else:
return '', 404
elif request.method == 'PUT':
json = {"modules": request.form['modules'],
"hits":request.form['hits'],
"customs":request.form['customs'],
"free":request.form['free'],
"bads":request.form['bads'],
"checked":request.form['checked'],
"remaining":request.form['remaining'],
"retries":request.form['retries'],
"errors":request.form['errors'],
"cpm":request.form['cpm']
}
print(1)
todos[todo_id] = json
print(1)
return {todo_id: todos[todo_id]}
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8080, debug=True)
And my client code is like this,
import requests
params = (
('cpm', '123'),
("modules", "doordash|COD"),
("hits", '63242'),
("customs", "888"),
("free", "233"),
("bads", "3892"),
("checked", '20000'),
("remaining", '200000'),
("retries", "1000"),
("errors", '1234')
)
response = requests.put('https://animeaskedforitt.my name.repl.co/123?modules=edigubv', params=params)
print(response)
r = requests.get("https://animeaskedforitt.myname.repl.co/123").text
print(r)
Every time I run it I get a 500 error from the put request and a 200 succes code.
In the console I get a 400 error saying “bad request” and a python error of KeyError: module
Thanks for your help

Related

FastAPI and Flask response issue

I've below code of Flask calling FastAPI end point. But the response not getting generated(Error: 422) when the FastAPI end point is being invoked and FastAPI end point log says INFO:127.0.0.1:56904 - "POST /runquery HTTP/1.1" 422 Unprocessable Entity
Inputs to FASTAPI end point
query : select c2,c2,c4,c5 from table_tab
env= iAT
Flask Code
import requests
app = Flask(__name__)
#app.route("/", methods=["GET", "POST"])
def index():
query_id = ""
query = ""
status = ""
env = ""
if request.method == "POST":
query = request.form["query"]
env = request.form["env"]
data = {"query": query, "env": env}
print(data)
headers = {'Content-Type': 'application/json'}
**response = requests.post("http://localhost:8000/runquery", json=data,headers=headers)**
print(response)
if response.status_code != 200:
return f'Error: {response.status_code}'
else:
print(response.json())
response_data = response.json()
query_id = response_data["query_id"]
status = response_data["status"]
return render_template("index.html", query_id=query_id, query=query, status=status, env=env)
if __name__ == "__main__":
app.run(debug=True) ```
**Here is the FastAPI end point code**
``` #app.post("/runquery")
async def runquery(query: str, env: str):
print('.....')
delay = 60
parsed_query = sqlparse.parse(query)[0]
if parsed_query.get_type() == "SELECT":
pass
else:
return JSONResponse(content={"error": "Only SELECT queries are allowed"}, status_code=422)
# return {"error": "Only SELECT queries are allowed"}
registry_scheduled = ScheduledJobRegistry(queue=que)
registry_started = StartedJobRegistry(queue=que)
# registry_completed = FinishedJobRegistry(queue=que)
# registry_failed = FailedJobRegistry(queue=que)
if len(registry_scheduled.get_job_ids()) >= 2:
return JSONResponse(content={"Info": "GQs are already in-progress. Try after some time"})
# return {"Info": "GQs are already in-progress. Try after some time"}
if len(registry_started.get_job_ids()) >= 2:
return JSONResponse(content={"Info": "GQs are already in-progress.Try after some time"})
# return {"Info": "GQs are already in-progress.Try after some time"}
# Generate a unique ID for the query
query_id = str(uuid.uuid4())
print('query_id..........', query_id)
directory_path = os.path.join(home_path, query_id)
print(directory_path)
if not os.path.exists(directory_path):
os.makedirs(directory_path)
file_path = os.path.join(directory_path, "query.sql")
with open(file_path, "w") as f:
f.write(query)
# job = que.enqueue(exec_query, query, env, sqlfile)
job = que.enqueue_in(timedelta(seconds=delay), exec_query, query, env, query_id)
r.set(query_id, job.id)
# Return the query ID to the user
return JSONResponse(content={"query_id": query_id, "query": query, "stauts": "OK"},
status_code=202) ```
422 is Unprocessable Entity, it means that your request sent has wrong format parameter in the body. You must use Pydantic class to validate json.
Change FastAPI endpoint in this way :
from pydantic import BaseModel
class Data(BaseModel):
query: str
env: str
#app.post("/runquery")
async def runquery(data: Data):
...

How to send a file to post method that accepts form data in python flask, and also how to retrieve file and other fields in the called method?

I'm trying something like this.
Caller code -
files = {'file': open(file_name, 'rb').read()}
response = requests.post(url, headers=headers, data=metadata, files=files)
Called method code-
metadata = {}
for key, value in request.form.items():
metadata[key] = value
print(metadata)
print(type(metadata))
print("Request data")
print(request.data)
print("Files")
print(request.files)
print(request.files is None)
print('file' not in request.files)
The output in called method is empty
{}
<class 'dict'>
Request data
b''
Files
ImmutableMultiDict([])
False
True
Can someone tell me how to fix this?
files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}
r = requests.post(url, files=files, data=values)
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/', methods=['POST'])
def upload_file():
uploaded_file = request.files['file']
if uploaded_file.filename != '':
uploaded_file.save(uploaded_file.filename)
return redirect(url_for('index'))

KeyError on POST method in simple Flask python backend

I'm trying to create a simple API and server with MongoDB and Flask in python(pycharm). I'm testing the methods with Postman and so far the GET and DELETE methods work. I'm having troubles with the POST method mainly(for adding an entity). I have 2 classes
repository class
class ExercisesRepository:
def __init__(self):
self.client = MongoClient('localhost', 27017)
self.client.drop_database("exercise_database") # clear everything that was before
self.db = self.client.exercise_database # create database
self.exercises = self.db.exercises # create table in the database
def get_all(self):
return [{
'id': str(exercise['_id']),
'type': exercise['type'],
'calories': exercise['calories']
} for exercise in self.exercises.find()]
def add(self, exercise):
exercise = {key: exercise[key] for key in exercise}
exercise['calories'] = int(exercise['calories']) #line 24
self.exercises.insert_one(exercise) # automatically generates an ObjectId for the exercise
return 200
def update(self, exercise_id, exercise):
my_query = {"_id": ObjectId(exercise_id)}
new_values = {"$set": {"type": exercise["type"], "calories": exercise["calories"]}}
self.exercises.update_one(my_query, new_values)
return 200
def delete(self, exercise_id):
self.exercises.remove(ObjectId(exercise_id))
return 200
def check_database_content(self):
for exercise in self.exercises.find():
pprint.pprint(exercise)
server class
from ExercisesRepository import ExercisesRepository
from flask import Flask
from flask import request
from flask import jsonify
import sys
app = Flask(__name__)
exerciseRepo = ExercisesRepository()
exerciseRepo.add({'type': 'Yoga', 'calories': 500})
exerciseRepo.add({'type': 'Walk', 'calories': 300})
exerciseRepo.add({'type': 'Run', 'calories': 100})
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route("/exercises", methods=['GET', 'POST'])
def exercises():
if request.method == 'GET':
return jsonify(exerciseRepo.get_all())
elif request.method == 'POST':
print(request.form, file=sys.stderr)
return jsonify(exerciseRepo.add(request.form)) #line 31
#app.route('/exercises/<exercise_id>', methods=['PUT', 'DELETE'])
def exercises_id(exercise_id):
if request.method == 'PUT':
print(request.form, file=sys.stderr)
return jsonify(exerciseRepo.update(exercise_id, request.form))
elif request.method == 'DELETE':
return jsonify(exerciseRepo.delete(exercise_id))
if __name__ == '__main__':
app.run()
When I try to make a POST call in postman with a JSON like this :
{
"type": "Aerobic",
"calories": 500
} I get the following message in postman: 500 Internal Server Error
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
and in Pycharm console:
File "server.py", line 31, in exercises
return jsonify(exerciseRepo.add(request.form))
server\ExercisesRepository.py", line 24, in add
exercise['calories'] = int(exercise['calories'])
KeyError: 'calories'
127.0.0.1 - - [05/Jan/2020 13:01:50] "POST /exercises HTTP/1.1" 500 -
I'm pretty new to python and this is my first try to make an api so if you could explain as much as possible it would be very helpful. Thanks!
If you send data as JSON then you have to get it using request.json, not request.form
from flask import Flask, request, jsonify
app = Flask(__name__)
#app.route("/exercises", methods=['GET', 'POST'])
def exercises():
print('form:', request.form)
print('json:', request.json)
return jsonify(request.json) #line 31
if __name__ == '__main__':
app.run()
When you send as JSON
import requests
r = requests.post('http://localhost:5000/exercises', json={'type': 'Run', 'calories': 100})
then server shows
form: ImmutableMultiDict([])
json: {'type': 'Run', 'calories': 100}
When you send as form data
import requests
r = requests.post('http://localhost:5000/exercises', data={'type': 'Run', 'calories': 100})
then server shows
form: ImmutableMultiDict([('type', 'Run'), ('calories', '100')])
json: None
form sends data as string type=Run&calories=100 in body,
json sends data as string {'type': 'Run', 'calories': 100} in body.
You can see it if you display request's body
import requests
r = requests.post('https://httpbin.org/post', data={'type': 'Run', 'calories': 100})
print(r.request.body)
r = requests.post('https://httpbin.org/post', json={'type': 'Run', 'calories': 100})
print(r.request.body)
Result
type=Run&calories=100
b'{"type": "Run", "calories": 100}'

How to handle multiple WSGI applications in Flask?

I'm a newbie in Flask and was wondering how to implement Flask API (http://www.flaskapi.org/) along with the main website, for example, main website (/), access API (/api/). In fact, this gives me an Internal Server Error.
Thank you.
from flask import Flask, request, url_for
from flask.ext.api import FlaskAPI, status, exceptions
# the all-important app variable:
app = Flask(__name__)
app2 = FlaskAPI(__name__)
#app.route("/")
def hello():
return "Oh, Hello Worldaa"
notes = {
0: 'do the shopping',
1: 'build the codez',
2: 'paint the door',
}
def note_repr(key):
return {
'url': request.host_url.rstrip('/api/') + url_for('notes_detail', key=key),
'text': notes[key]
}
#app2.route("/api/", methods=['GET', 'POST'])
def notes_list():
"""
List or create notes.
"""
if request.method == 'POST':
note = str(request.data.get('text', ''))
idx = max(notes.keys()) + 1
notes[idx] = note
return note_repr(idx), status.HTTP_201_CREATED
# request.method == 'GET'
return [note_repr(idx) for idx in sorted(notes.keys())]
#app2.route("/api/<int:key>/", methods=['GET', 'PUT', 'DELETE'])
def notes_detail(key):
"""
Retrieve, update or delete note instances.
"""
if request.method == 'PUT':
note = str(request.data.get('text', ''))
notes[key] = note
return note_repr(key)
elif request.method == 'DELETE':
notes.pop(key, None)
return '', status.HTTP_204_NO_CONTENT
# request.method == 'GET'
if key not in notes:
raise exceptions.NotFound()
return note_repr(key)
if __name__ == "__main__":
app.run(debug=True)
app2.run(debug=True)
You can look at Blueprint in the documentation of Flask.
For example:
main = Blueprint(__name__)
#main.route("/")
def index():
return "Hello, World."
api = Blurprint(__name__)
#api.route("/test")
def test():
return jsonify(dict(test="test")})
app = Flask(__name__)
app.register_blueprint(main)
app.register_blueprint(api, url_prefix="/api")
and then, you access index page by http://example.com, access api by http://example.com/api/test

Missing_uri parameter when using facebook oauth

I am using flask-oauth to authenticate my users.
I did a bit of digging and I found out that this is the URL that flask-oauth is sending:
https://www.facebook.com/dialog/oauth?response_type=code&client_id=1000000000000&redirect_uri=http%3A%2F%2Fwww.resoorce.com%2Flogin%2Fauthorized&scope=email
It clearly has a redirect_uri parameter!
This is the response that facebook is sending back:
{"error":{"message":"Missing redirect_uri parameter.","type":"OAuthException","code":191}}
If it helps this is my whole code:
from flask import Flask, redirect, url_for, session, request
from flask_oauthlib.client import OAuth, OAuthException
'''fake ones'''
FACEBOOK_APP_ID = '123121321212312313'
FACEBOOK_APP_SECRET = 'dfg12sdf1g2s1dfg31sd3fg'
app = Flask(__name__)
app.debug = True
app.secret_key = 'development'
oauth = OAuth(app)
facebook = oauth.remote_app(
'facebook',
consumer_key=FACEBOOK_APP_ID,
consumer_secret=FACEBOOK_APP_SECRET,
request_token_params={'scope': 'email'},
base_url='https://graph.facebook.com',
request_token_url=None,
access_token_url='/oauth/access_token',
authorize_url='https://www.facebook.com/dialog/oauth'
)
#app.route('/')
def index():
return redirect(url_for('login'))
#app.route('/login')
def login():
callback = url_for(
'facebook_authorized',
next=request.args.get('next') or request.referrer or None,
_external=True
)
return facebook.authorize(callback=callback)
#app.route('/login/authorized')
#facebook.authorized_handler
def facebook_authorized(resp):
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
if isinstance(resp, OAuthException):
return 'Access denied: %s' % resp.message
session['oauth_token'] = (resp['access_token'], '')
me = facebook.get('/me')
return 'Logged in as id=%s name=%s redirect=%s' % \
(me.data['id'], me.data['name'], request.args.get('next'))
#facebook.tokengetter
def get_facebook_oauth_token():
return session.get('oauth_token')
ain__':
app.run()
if __name__ == '__main__':
app.run()

Categories

Resources