I am trying to send a form data through flutter to my flask webserver but the flask server is not receiving the request. Below is my flutter code
class FetchData {
Future<Price> getData(
int area,
int bedrooms,
double? psf,
int feature_score,
double? locationPremium,
) async {
const uri = 'http://127.0.0.1:5000/predict';
var map = <String, dynamic>{};
map['area'] = area;
map['bedrooms'] = bedrooms;
map['psf'] = psf;
map['feature_score'] = feature_score;
map['location_premium'] = locationPremium;
map['log_premium'] = log(locationPremium!);
http.Response response = await http.post(Uri.parse(uri), body: map);
if (response.statusCode == 200) {
return Price.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load post');
}
}
}
And below is my app.py code
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
import pickle
import numpy as np
model=pickle.load(open('model1.pkl','rb'))
app = Flask(__name__)
#app.route('/')
def home():
return "Hello World"
#app.route('/predict',methods=['POST'])
def predictor():
area=int(request.form['area'])
bedrooms=int(request.form['bedrooms'])
psf=float(request.form['psf'])
feature_score=int(request.form['feature_score'])
LocationPremium=float(request.form['LocationPremium'])
LogPremium=float(request.form['LogPremium'])
query=np.array([[area,bedrooms,psf,feature_score,LocationPremium,LogPremium]])
result= model.predict(query)[0]
return jsonify({'prediction':str(result)})
if __name__ == '__main__':
app.run(debug=True)
app.run(host='0.0.0.0', port=5000)
I have tried sending the request through postman and the server is receiving the POST request
You need to add headers to your post request.
Future post( Uri url, { Map ? headers, Object? body, Encoding? encoding, })
im quite new to coding but this is barely documented so i need some help.
Im building a flask application but I cant get the google auth flow working.
Im using Pycharm and python version 3.9
My issues are :
I cant find any beginner tutorial that explains how to go through the Auth flow.
I dont understand how to interact with google APis through flask. (i want to use the android-management-api)
I do understand that i need to create a service object but that only works when i can authenticate the google flow and this is where im already stuck for 5 days now.
I already followed the instructions from realpython and MattButton.
when trying these instructions i keep getting errors.
now im getting:
Error: While importing 'app', an ImportError was raised:
Traceback (most recent call last):
File "C:\000 Projects\Applications\PY\flaskProjects\MDM\venv\lib\site-packages\flask\cli.py", line 256, in locate_app
__import__(module_name)
File "C:\000 Projects\Applications\PY\flaskProjects\MDM\app.py", line 5, in <module>
from flask_oauth import OAuth
File "C:\000 Projects\Applications\PY\flaskProjects\MDM\venv\lib\site-packages\flask_oauth.py", line 13, in <module>
from urlparse import urljoin
ModuleNotFoundError: No module named 'urlparse'
Process finished with exit code 2
Can somebody explain me what im doing wrong
my code is below:
from flask import Flask, redirect, url_for, session, request, jsonify, render_template
from datetime import datetime
from flask import Flask, redirect, url_for, session
from flask_oauth import OAuth
import urllib.parse
# You must configure these 3 values from Google APIs console
# https://code.google.com/apis/console
GOOGLE_CLIENT_ID = ''
GOOGLE_CLIENT_SECRET = ''
REDIRECT_URI = '/authorized' # one of the Redirect URIs from Google APIs console
SECRET_KEY = 'development key'
DEBUG = True
app = Flask(__name__)
app.debug = DEBUG
app.secret_key = SECRET_KEY
oauth = OAuth()
google = oauth.remote_app('google',
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
request_token_params={'scope': 'https://www.googleapis.com/auth/androidmanagement',
'response_type': 'code'},
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
access_token_params={'grant_type': 'authorization_code'},
consumer_key=GOOGLE_CLIENT_ID,
consumer_secret=GOOGLE_CLIENT_SECRET)
#app.route('/')
def index():
access_token = session.get('access_token')
if access_token is None:
return redirect(url_for('login'))
access_token = access_token[0]
from urllib.request import Request, urlopen
from urllib.error import URLError
headers = {'Authorization': 'OAuth '+access_token}
req = Request('https://www.googleapis.com/oauth2/v1/userinfo',
None, headers)
try:
res = urlopen(req)
except URLError as e:
if e.code == 401:
# Unauthorized - bad token
session.pop('access_token', None)
return redirect(url_for('login'))
return res.read()
return res.read()
#app.route('/login')
def login():
callback = url_for('authorized', _external=True)
return google.authorize(callback=callback)
#app.route(REDIRECT_URI)
#google.authorized_handler
def authorized(resp):
access_token = resp['access_token']
session['access_token'] = access_token, ''
return redirect(url_for('index'))
#google.tokengetter
def get_access_token():
return session.get('access_token')
#app.route('/home')
def home():
return render_template(
'index.html',
title='Home Page',
year=datetime.now().year,
)
#app.route('/devices')
def devices():
return render_template(
'devices.html',
title='Devices',
year=datetime.now().year,
)
#app.route('/policies')
def policies():
return render_template(
'policies.html',
title='Policies',
year=datetime.now().year,
)
#app.route('/enterprises')
def enterprises():
return render_template(
'enterprises.html',
title='Enterprises',
year=datetime.now().year,
)
#app.route('/contact')
def contact():
# """Renders the contact page."""
return render_template(
'contact.html',
title='Contact',
year=datetime.now().year,
message='ICS-Vertex'
)
#app.route('/about')
def about():
return render_template(
'about.html',
title='About',
year=datetime.now().year,
message='Your application description page.'
)
if __name__ == '__main__':
app.run()
Solved!
I found out that there were 2 conflicting libraries that both used the requests name
Flask.requests
Requests
I have the following flask api, which just returns echo of its input:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class query(Resource):
def get(self, a_string):
return{
'original': a_string,
'echo': a_string
}
api.add_resource(query,'/echo/<a_string>')
if __name__ == '__main__':
app.run()
Then, when I try to use python requests to make queries to my api:
import json
def query(text):
payload = {'echo': str(text)}
headers = {'content-type': 'application/x-www-form-urlencoded'}
r = requests.request("POST", 'http://127.0.0.1:5000', data=payload, headers=headers)
print(r)
#data = json.loads(r.text)
#return data
query('hi')
I keep getting:
<Response [404]>
Any idea of how to fix this issue? Interestingly when I go to my browser and do:
http://127.0.0.1:5000/echo/hi
I get:
{"original": "hi", "echo": "hi"}
But sending a POST to / with a payload of {"echo": whatever} is not at all the same as sending a GET to /echo/whatever. Your API expects the latter.
def query(text):
r = requests.get("http://127.0.0.1:5000/echo/{}".format(text))
Or, change your API so it does expect that:
class query(Resource):
def post(self):
a_string = request.form["echo"]
return {
'original': a_string,
'echo': a_string
}
api.add_resource(query, '/')
I'm using a google authentication based on the following example. Everything was working and then suddendly when I tried to login I started getting this error:
httplib2.ServerNotFoundError ServerNotFoundError: Unable to find the
server at accounts.google.com
Any ideas on what might be wrong?
from flask import Flask, redirect, url_for, session
from flask_oauth import OAuth
# You must configure these 3 values from Google APIs console
# https://code.google.com/apis/console
GOOGLE_CLIENT_ID = '<Client-ID>'
GOOGLE_CLIENT_SECRET = '<Client-secret>'
REDIRECT_URI = '/authorized' # one of the Redirect URIs from Google APIs console
SECRET_KEY = 'development key'
DEBUG = True
app = Flask(__name__)
app.debug = DEBUG
app.secret_key = SECRET_KEY
oauth = OAuth()
google = oauth.remote_app('google',
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
request_token_params={'scope': 'https://www.googleapis.com/auth/userinfo.email',
'response_type': 'code'},
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
access_token_params={'grant_type': 'authorization_code'},
consumer_key=GOOGLE_CLIENT_ID,
consumer_secret=GOOGLE_CLIENT_SECRET)
#app.route('/')
def index():
access_token = session.get('access_token')
if access_token is None:
return redirect(url_for('login'))
access_token = access_token[0]
from urllib2 import Request, urlopen, URLError
headers = {'Authorization': 'OAuth '+access_token}
req = Request('https://www.googleapis.com/oauth2/v1/userinfo',
None, headers)
try:
res = urlopen(req)
except URLError, e:
if e.code == 401:
# Unauthorized - bad token
session.pop('access_token', None)
return redirect(url_for('login'))
return res.read()
return res.read()
#app.route('/login')
def login():
callback=url_for('authorized', _external=True)
return google.authorize(callback=callback)
#app.route(REDIRECT_URI)
#google.authorized_handler
def authorized(resp):
access_token = resp['access_token']
session['access_token'] = access_token, ''
return redirect(url_for('index'))
#google.tokengetter
def get_access_token():
return session.get('access_token')
def main():
app.run()
if __name__ == '__main__':
main()
I've had this problem before and the fix was to disable IPv6 on my computer. For some reason Google and IPv6 don't play well together.
If you're on a Mac, the command is:
sudo networksetup -setv6off wi-fi
Make sure to turn it back on when you're done:
sudo networksetup -setv6automatic wi-fi
I am trying to make a cross origin request using jquery but it keeps being reject with the message
XMLHttpRequest cannot load http://... No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin ... is therefore
not allowed access.
I am using flask, heroku, and jquery
the client code looks like this:
$(document).ready(function() {
$('#submit_contact').click(function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://...',
// data: [
// { name: "name", value: $('name').val()},
// { name: "email", value: $('email').val() },
// { name: "phone", value: $('phone').val()},
// { name: "description", value: $('desc').val()}
//
// ],
data:"name=3&email=3&phone=3&description=3",
crossDomain:true,
success: function(msg) {
alert(msg);
}
});
});
});
on the heroku side i am using flask and it is like this
from flask import Flask,request
from flask.ext.mandrill import Mandrill
try:
from flask.ext.cors import CORS # The typical way to import flask-cors
except ImportError:
# Path hack allows examples to be run without installation.
import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0, parentdir)
from flask.ext.cors import CORS
app = Flask(__name__)
app.config['MANDRILL_API_KEY'] = '...'
app.config['MANDRILL_DEFAULT_FROM']= '...'
app.config['QOLD_SUPPORT_EMAIL']='...'
app.config['CORS_HEADERS'] = 'Content-Type'
mandrill = Mandrill(app)
cors = CORS(app)
#app.route('/email/',methods=['POST'])
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __name__ == '__main__':
app.run()
Here is what worked for me when I deployed to Heroku.
http://flask-cors.readthedocs.org/en/latest/
Install flask-cors by running -
pip install -U flask-cors
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route("/")
#cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
I've just faced the same issue and I came to believe that the other answers are a bit more complicated than they need to be, so here's my approach for those who don't want to rely on more libraries or decorators:
A CORS request actually consists of two HTTP requests. A preflight request and then an actual request that is only made if the preflight passes successfully.
The preflight request
Before the actual cross domain POST request, the browser will issue an OPTIONS request. This response should not return any body, but only some reassuring headers telling the browser that it's alright to do this cross-domain request and it's not part of some cross site scripting attack.
I wrote a Python function to build this response using the make_response function from the flask module.
def _build_cors_preflight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add("Access-Control-Allow-Methods", "*")
return response
This response is a wildcard one that works for all requests. If you want the additional security gained by CORS, you have to provide a whitelist of origins, headers and methods.
This response will convince your (Chrome) browser to go ahead and do the actual request.
The actual request
When serving the actual request you have to add one CORS header - otherwise the browser won't return the response to the invoking JavaScript code. Instead the request will fail on the client-side. Example with jsonify
response = jsonify({"order_id": 123, "status": "shipped"})
response.headers.add("Access-Control-Allow-Origin", "*")
return response
I also wrote a function for that.
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
allowing you to return a one-liner.
Final code
from flask import Flask, request, jsonify, make_response
from models import OrderModel
flask_app = Flask(__name__)
#flask_app.route("/api/orders", methods=["POST", "OPTIONS"])
def api_create_order():
if request.method == "OPTIONS": # CORS preflight
return _build_cors_preflight_response()
elif request.method == "POST": # The actual request following the preflight
order = OrderModel.create(...) # Whatever.
return _corsify_actual_response(jsonify(order.to_dict()))
else:
raise RuntimeError("Weird - don't know how to handle method {}".format(request.method))
def _build_cors_preflight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
OK, I don't think the official snippet mentioned by galuszkak should be used everywhere, we should concern the case that some bug may be triggered during the handler such as hello_world function. Whether the response is correct or uncorrect, the Access-Control-Allow-Origin header is what we should concern. So, it is very simple, just like the snippet bellow:
# define your bluprint
from flask import Blueprint
blueprint = Blueprint('blueprint', __name__)
# put this sippet ahead of all your bluprints
# blueprint can also be app~~
#blueprint.after_request
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
# Other headers can be added here if needed
return response
# write your own blueprints with business logics
#blueprint.route('/test', methods=['GET'])
def test():
return "test success"
That is all~~
If you want to enable CORS for all routes, then just install flask_cors extension (pip3 install -U flask_cors) and wrap app like this: CORS(app).
That is enough to do it (I tested this with a POST request to upload an image, and it worked for me):
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
Important note: if there is an error in your route, let us say you try to print a variable that does not exist, you will get a CORS error related message which, in fact, has nothing to do with CORS.
I resolved this same problem in python using flask and with this library.
flask_cors
in file init.py:
#pip install flask_cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
cors = CORS(app, resource={
r"/*":{
"origins":"*"
}
})
and its all.
Reference: https://flask-cors.readthedocs.io/en/latest/
Improving the solution described here: https://stackoverflow.com/a/52875875/10299604
With after_request we can handle the CORS response headers avoiding to add extra code to our endpoints:
### CORS section
#app.after_request
def after_request_func(response):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
response = make_response()
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'x-csrf-token')
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
else:
response.headers.add('Access-Control-Allow-Credentials', 'true')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
return response
### end CORS section
All the responses above work okay, but you'll still probably get a CORS error, if the application throws an error you are not handling, like a key-error, if you aren't doing input validation properly, for example. You could add an error handler to catch all instances of exceptions and add CORS response headers in the server response
So define an error handler - errors.py:
from flask import json, make_response, jsonify
from werkzeug.exceptions import HTTPException
# define an error handling function
def init_handler(app):
# catch every type of exception
#app.errorhandler(Exception)
def handle_exception(e):
#loggit()!
# return json response of error
if isinstance(e, HTTPException):
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": e.code,
"name": e.name,
"description": e.description,
})
else:
# build response
response = make_response(jsonify({"message": 'Something went wrong'}), 500)
# add the CORS header
response.headers['Access-Control-Allow-Origin'] = '*'
response.content_type = "application/json"
return response
then using Billal's answer:
from flask import Flask
from flask_cors import CORS
# import error handling file from where you have defined it
from . import errors
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
errors.init_handler(app) # initialise error handling
Try the following decorators:
#app.route('/email/',methods=['POST', 'OPTIONS']) #Added 'Options'
#crossdomain(origin='*') #Added
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __name__ == '__main__':
app.run()
This decorator would be created as follows:
from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper
def crossdomain(origin=None, methods=None, headers=None,
max_age=21600, attach_to_all=True,
automatic_options=True):
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, basestring):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, basestring):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()
def get_methods():
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp
h = resp.headers
h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
if headers is not None:
h['Access-Control-Allow-Headers'] = headers
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator
You can also check out this package Flask-CORS
You'd first need to install flask-cors. You can do this as follows:
pip install flask-cors
Once this is installed, you can use it in your Flask app as follows:
If you need to enable CORS for all routes:
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
If you want to enable CORS only for specific routes, you can pass the resources parameter to the CORS function.
For example,
CORS(app, resources={r"/api/*": {"origins": "*"}})
In this example, This code will enable CORS only for routes that start with /api/ and will allow requests from any origin. You can customize the resources parameter to match your needs.
For more information, please read the documentation
My solution is a wrapper around app.route:
def corsapp_route(path, origin=('127.0.0.1',), **options):
"""
Flask app alias with cors
:return:
"""
def inner(func):
def wrapper(*args, **kwargs):
if request.method == 'OPTIONS':
response = make_response()
response.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
response.headers.add('Access-Control-Allow-Headers', ', '.join(origin))
response.headers.add('Access-Control-Allow-Methods', ', '.join(origin))
return response
else:
result = func(*args, **kwargs)
if 'Access-Control-Allow-Origin' not in result.headers:
result.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
return result
wrapper.__name__ = func.__name__
if 'methods' in options:
if 'OPTIONS' in options['methods']:
return app.route(path, **options)(wrapper)
else:
options['methods'].append('OPTIONS')
return app.route(path, **options)(wrapper)
return wrapper
return inner
#corsapp_route('/', methods=['POST'], origin=['*'])
def hello_world():
...
If you can't find your problem and you're code should work, it may be that your request is just reaching the maximum of time heroku allows you to make a request. Heroku cancels requests if it takes more than 30 seconds.
Reference: https://devcenter.heroku.com/articles/request-timeout