I'm developing a small program which inserts a data obtained by curl to a MySQL database. Unfortunately, I haven't found any similar about my question, so if you have something on your mind - please point me out there. Here is what I tried so far
import os
import pymysql
from flask import Flask, request
app = Flask(__name__)
db = pymysql.connect("127.0.0.1","meeting_admin","password","rooms")
cur = db.cursor()
#app.route('/book_room', methods = ['POST'])
def book_room():
try:
room = request.form['room']
book_date = request.form['book_date']
booked_by = request.form['booked_by']
cur.execute("INSERT INTO booked_rooms(room, book_date, booked_by)
VALUES ('%c', '%d', '%s')",(room, book_date, booked_by))
db.commit()
cur.close()
return "OK\n", 200
except:
db.rollback()
return "Smth went wrong", 500
db.close()
if __name__ == '__main__':
app.run()
And the curl command is:
curl -H "Content-type: application/json" -X POST /
http://127.0.0.1:5000/book_room -d /
'{room=602,book_date:27-08-2019,booked_by="someone"}'
And what I'm getting is:
File "server_flask.py", line 23, in book_room
room = request.form['room']
File "/usr/local/lib/python3.5/dist-
packages/werkzeug/datastructures.py", line 431, in __getitem__
raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.HTTPException.wrap.<locals>.newcls: 400 Bad
Request: The browser (or proxy) sent a request that this server could
not understand.
Thanks in advance.
Related
I have this simple code for testing:
from fastapi import FastAPI
import uvicorn
import requests
app = FastAPI()
#app.get('/', status_code=200)
def index():
return {'message':'Hello, World!'}
#app.post('/', status_code=201)
def index_post():
dicti = request.form.to_dict()
print(dicti['key'])
return {'message':'Hello, Post!'}
if __name__ == "__main__":
uvicorn.run(
"views:app",
host="localhost",
port=5000,
reload=True
)
And I want to check if the post works. I ran in the cmd this:
curl --request POST -d'{"key":"it works","pas":"la"}' http://327ffe2d90b9.ngrok.io/
But instead of printing it works in the terminal as I was expecting, it returned Internal Server Error.
Please help:
I am trying to create a webservice in flask (this is my first time) that takes a str, queries an external mysql database and returns 1 row as json.
I am sure there are other of issues with the code below (all suggestions much appreciated), but I cannot even see them yet, because when I try to access example.com/webservice/vin/ I get "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." from nginx.
PLease can someone guide me where I am going wrong?
example.com return Hello from app_name running in docker...yayy. Its the other route that isnt working.
from flask.ext.mysqldb import MySQL
import json
app.config['MYSQL_HOST'] = 'xxx'
app.config['MYSQL_USER'] = 'xxx'
app.config['MYSQL_PASSWORD'] = 'xxx'
app.config['MYSQL_DB'] = 'xxx'
mysql = MySQL(app)
#app.route("/")
def index():
# Use os.getenv("key") to get environment variables
app_name = os.getenv("APP_NAME")
if app_name:
return f"Hello from {app_name} running in a Docker container behind Nginx!"
return "Hello from Flask"
#app.route('/webservice/vin/<vin>', methods=['GET'])
def get_vehicle(vin):
sql = "SELECT * FROM `table` where column = '(%s )';" %(vin)
cur = mysql.connection.cursor()
cur.execute(sql)
row_headers=[x[0] for x in cur.description] #this will extract row headers
rv = cur.fetchall()
json_data=[]
for result in rv:
json_data.append(dict(zip(row_headers,result)))
return json.dumps(json_data)
from flask import make_response
#app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
I am trying to develop as a service where someone can send the csv file to my REST API which I dump in the database. My cURL request is reading the data but flask_restful is not able to process it. Can you please tell me what am I doing wrong and how can I fix it?
[EDITED BELOW]
I found after reading the docs that request.files lets you read the files from the POST request from a form. I also found a way to send a csv file through cURL as a form.
class ForBetaAndUpload(Resource):
def post(self, kind='quotes'):
# parser = reqparse.RequestParser()
file = request.files['file']
print(file)
# kind = parser.add_argument('kind').parse_args()['kind']
if kind:
if file and file[-3:]=='csv':
if kind == 'quotes':
try:
df = pd.read_csv(file)
df.to_sql('QUOTES', helper.conx, index=False, if_exists='append')
return jsonify({'message':'%s rows inserted in the databasee table successfully' %(df.shape[0])})
except Exception as e:
return jsonify({'exception': e})
if kind == 'trace':
try:
df = pd.read_csv(todos)
df.iloc[:10].to_sql('TRACE', helper.conx, index=False, if_exists='append')
return jsonify({'message':'%s rows inserted in the databasee table successfully' %(df.shape[0])})
except Exception as e:
return jsonify({'message': e})
else:
return jsonify({'message': 'Please provide a csv file'})
else:
return jsonify({'message':'Please provide the file for to update relevant table in the databse'})
api.add_resource(ForBetaAndUpload, '/upload', endpoint='upload')
if __name__ == "__main__":
app.run(debug=True)
cURL Request:
curl "https://localhost:5000/upload" -X POST -H 'Content-Type: txt/csv' -d trace.csv --insecure
I'm getting the following message:
curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol
API Error Message
code 400, message Bad HTTP/0.9 request type
('\x16\x03\x01\x02\x00\x01\x00\x01ü\x03\x03\x08Ú:ü^¢Ù~ö7W\x9fDyy\x16j\x7fõ>½\x82\x90uÎ&3ÿZ\x08êE\x00\x00')
How can I send a csv file to the flask restful_api. Is it right what I am doing or is there any other way to do it?
My solution to read csv from Flask is:
in Flask:
f = request.files['file']
f will be a handler to the file, you can then use csv_reader.
and to send the file:
curl -s "http://localhost:5000" \
-F file=#./myfile.csv \
-X POST \
-H 'enctype:multipart/form-data ; Content-Type:multipart/form-data'
And that should works. Let me know.
Question. I would like to create a REST API for the data stored in an Azure SQL DB that will allow me to do GET and POST operation using Python. Currently I managed to print the results of my query on the terminal but how do I convert it to JSON format and allow it to run 24/7 on linux (perhaps change port?)? Below is my script:
import pyodbc
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Energy(Resource):
def get(self):
server = 'testserver.database.windows.net'
database = 'testdb'
username = 'admin'
password = '735t'
driver= '{ODBC Driver 13 for SQL Server}'
connexion = pyodbc.connect('DRIVER='+driver+';PORT=1433;SERVER='+server+';PORT=1443;DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = connexion.cursor()
cursor.execute("SELECT TOP (100) * FROM [dbo].[Power_Meter]")
row = cursor.fetchone()
while row:
GeneratedCode = str(row[0])
ReportedDate = str(row[1])
print (str(row[0]) + " " + str(row[1]))
row = cursor.fetchone()
rest_row = jsonify(row)
return rest_row
api.add_resource(Energy, '/DPM')
if __name__ == '__main__':
app.run(debug=True)
and this is the output result on localhost:5000/DPM
null
Can anyone suggest me how to go about solving this issue? Thanks
If you want to run your script 24/7 on Linux, you could execute it as a background task. Using nohup python sql.py>> test.log &
man nohup
nohup - run a command immune to hangups, with output to a non-tty
& to the command line to run in the background:
If you want to change port, just change like below:
app.run(host='0.0.0.0',port=5000)
I suggest you could store output to a file. Then you could parse data to json format.
I have read all related SO questions on this but I still keep encountering this error(400 - Bad Request) when posting json to my Flask app running on RedHat's openshift cloud platform.
This is my code:
flaskapp.py
import os
from datetime import datetime
from flask import Flask, request, flash, url_for, redirect, \
render_template, abort, send_from_directory
app = Flask(__name__)
app.config.from_pyfile('flaskapp.cfg')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/<path:resource>')
def serveStaticResource(resource):
return send_from_directory('static/', resource)
#app.route("/test")
def test():
return "<strong>It's Alive!</strong>"
#app.route('/mine', methods=['POST'])
def mine():
content = request.get_json(force=True)
print content
return "Success!\n"
if __name__ == '__main__':
app.run(debug=True)
This is how my app.py looks like
#!/usr/bin/env python
# This file may be used instead of Apache mod_wsgi to run your python
# web application in a different framework. A few examples are
# provided (cherrypi, gevent), but this file may be altered to run
# whatever framework is desired - or a completely customized service.
#
import imp
import os
import sys
try:
virtenv = os.path.join(os.environ.get('OPENSHIFT_PYTHON_DIR','.'), 'virtenv')
python_version = "python"+str(sys.version_info[0])+"."+str(sys.version_info[1])
os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib', python_version, 'site-packages')
virtualenv = os.path.join(virtenv, 'bin','activate_this.py')
if(sys.version_info[0] < 3):
execfile(virtualenv, dict(__file__=virtualenv))
else:
exec(open(virtualenv).read(), dict(__file__=virtualenv))
except IOError:
pass
#
# IMPORTANT: Put any additional includes below this line. If placed above this
# line, it's possible required libraries won't be in your searchable path
#
#
# main():
#
if __name__ == '__main__':
application = imp.load_source('app', 'flaskapp.py')
port = application.app.config['PORT']
ip = application.app.config['IP']
app_name = application.app.config['APP_NAME']
host_name = application.app.config['HOST_NAME']
fwtype="wsgiref"
for fw in ("gevent", "cherrypy", "flask"):
try:
imp.find_module(fw)
fwtype = fw
except ImportError:
pass
print('Starting WSGIServer type %s on %s:%d ... ' % (fwtype, ip, port))
if fwtype == "gevent":
from gevent.pywsgi import WSGIServer
WSGIServer((ip, port), application.app).serve_forever()
elif fwtype == "cherrypy":
from cherrypy import wsgiserver
server = wsgiserver.CherryPyWSGIServer(
(ip, port), application.app, server_name=host_name)
server.start()
elif fwtype == "flask":
from flask import Flask
server = Flask(__name__)
server.wsgi_app = application.app
server.run(host=ip, port=port)
else:
from wsgiref.simple_server import make_server
make_server(ip, port, application.app).serve_forever()
And this how am posting the data:
curl -X POST -H "application/json" -d '{"key":"val"}'
https://python-bonga.rhcloud.com/mine
N/B: This works fine on localhost
I found that a POST using curl without specifying the Content-Type defaults to sending Content-Type application/x-www-form-urlencoded
http://curl.haxx.se/docs/httpscripting.html#POST
And if the (different) mimetype exists in Flask, then the json data becomes unavailable; hence request.get_json(force=True) fails.
I therefore changed my code to look for form-data first before anything else
if request.form:
content = [item for item in request.form]
print "Content:", ''.join(content)
else:
content = request.get_json(force=True)
print "Content:", content