This is my Python. The input to it is
curl http://35.173.47.24:8090/put -d {"id":102} -X PUT
My code:
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
todos = {}
class TodoSimple(Resource):
def put(self):
i=request.form['id']
print(i)
api.add_resource(TodoSimple, '/put')
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8090,debug=True)
I need to pass json parameter. What do I have to change?
change the request to
curl -X PUT http://25.173.47.24:8080/put -d '{"id":102}' -H "Content-Type:application/json"
issue resolved issue was with code . request.get_json should be used
Related
I am trying to write a flask application that lets users select some options on a page, creates json string from them, and passes it to another 'build()' function, which is a flask route.
I should also be able to POST a json directly to build().
To avoid code duplication, I tried redirecting the 'Build' button in my form using code 307 and a json argument.
But I want to be able to pass it just as a curl request would do it with json content-type (option #1 below), so I can access the passed json using requests['json'], instead of requests.args['input']
def gui():
...
elif request.form['submit'] == 'Build':
return redirect(url_for('build', json=session['json']), code=307)
...
def build():
input = request.json #1. curl -H "Content-Type: application/json" --data #input.json http://localhost/build
input = json.loads(request.args['input']) #2. curl -H http://localhost/build?input=%7B"database"%3A...
...
How do I set my redirect, response, header etc. in the gui() 'Build' section ?
I have a simple flask API with file upload to send an image:
from flask import request
from flask import Flask
app = Flask(__name__)
#app.route('/', methods=['POST'])
def upload_file():
f = request.files['image']
print(f.content_type)
print(f.filename)
# do something with the file
# f.read()
return("Done")
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=5000)
When I send an image using curl's -F option, I can access the file:
curl -XPOST localhost:5000 -F "image=#img.jpg"
But how can I send an image as a payload in a json file with the -d option? If I encode the image using base64, put the string into a json file and send it with the -d option, it cannot find my image: KeyError: 'image'
I tried with different content types:
curl -XPOST localhost:5000 -d #img.json --header "Content-Type: application/json"
curl -XPOST localhost:5000 -d #img.json --header "Content-Type: image/jpeg"
My image.json looks something like this:
{"image":"/9j/4AAQSkZJRgABAQEAS..."}
(with the complete string instead of ...)
If you are sending data as JSON payload, you will have to use request.json to access them. Flask docs for files attribute state, that this attribute is non-empty when enctype="multipart/form-data". curl will set multipart/form-data header implicitly when you use -F option.
But for json data you have to set --header "Content-Type: application/json" as you have in you example. However, you have to check request.mimetype on the server side. Based on that check, you will either use files or json attribute. Here is the example how to handle those 2 cases:
from flask import request
from flask import Flask
app = Flask(__name__)
#app.route('/', methods=['POST'])
def upload_file():
if request.mimetype == 'multipart/form-data':
f = request.files['image']
print(f.content_type)
print(f.filename)
# do something with the file
# f.read()
else if request.mimetype == 'application/json':
f = request.json['image']
print(f)
# decode f from Base64
else:
# handle other mimetypes or return that selected mimetype is not supported
print('Unsupported content-type')
return("Done")
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=5000)
The curl command you used should be handled correctly:
curl -XPOST localhost:5000 -d #img.json --header "Content-Type: application/json"
Im making an Api that get two datas, "id" and "name", but i'm getting 'NoneType' object is not subscriptable" erro in name = request.json['Name']
from flask import Flask, jsonify, request, Response #import flask library
from checking import checker
app = Flask(__name__)
#app.route("/v1/products", methods=["GET", "POST"])
def getData():
user_id = request.json['id']
name = request.json['Name']
data = {'id' : user_id, 'Name' : name}
flag = checker(data)
if flag == True:
return 200, 'OK'
else:
return 403, 'Forbidden'
if __name__ == '__main__':
app.run(host='localhost', debug=True)
To send the data for API, i run the follow code:
curl -X POST -H "Content-Type: v1/products" -d '{'id' : '123', 'Name' : 'mesa'}' http://localhost:5000/v1/products
What i'm doing wrong ?
The issue isn't with your flask code but with your curl request. You aren't setting the content type and body properly, so there is no json for your API endpoint to process.
You'll want to change the first part of your command to: curl -X POST -H "Content-Type: application/json"
You may also have issues with your quotes in the request body, you'll either need to escape or modify the quotes so they aren't ambiguous.
This seem to work for me. Hope it does for you:
from flask import Flask, jsonify, request, Response #import flask library
app = Flask(__name__)
#app.route("/v1/products", methods=["GET", "POST"])
def getData():
user_id = request.args['id']
name = request.args['Name']
data = {'id' : user_id, 'Name' : name}
print(data)
if request.args != None:
print('OK')
else:
print('Forbidden')
return (data)
if __name__ == '__main__':
app.run(host='localhost', debug=True)
I have design web app using Flask for REST API server
for get id and key from frontend, backend will get info and do some action
(only using POST method)
curl command
curl -X POST -H "Content-Type:application/json" --data "{/"account_id/":/"100002/", /"access_key/":/"AKIAWDL6TY5M2INS6J7E/"}" https://192.168.172.130:443/account
However, when I am using curl command as below:
X POST -H "Content-Type:application/json" --data "{/"account_id/":/"100002/", /"access_key/":/"AKIAWDL6TY5M2INS6J7E/"}" https://192.168.172.130:443/account
curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - The token supplied to the function is invalid
code design in run.py
def scan_account(_account_id:str, _access_key:str):
# building connection to db
mySQLDB = mysqlDBConnector()
mySQLDB.dbConnection()
#init record log request
_now_time = datetime.datetime.now()
_request_info_log:str = 'Request of account id:'+str(_account_id)+' With Access Key: '+str(_access_key)+' at: '+str(_now_time)+' direction data: incoming with action type: post request'
mySQLDB.db_log_request_insert(_request_info_log)
# get secret key
_AccountID: int = _account_id
_AccessKey: str = _access_key
_SecretKey: str = mySQLDB.db_get_key(_AccountID,_AccessKey)
# init boto3 session
_aws_session = AWS_Session(_AccessKey, _SecretKey)
_aws_session.get_credentials()
#init running
_worker = Worker()
attrs = (getattr(_worker, name) for name in dir(_worker))
methods = filter(inspect.ismethod, attrs)
for method in methods:
_thread_method = threading.Thread(target=method, args=(_aws_session,))
_thread_method.start()
_thread_method.join()
#app.route("/account/",methods=["POST"])
def account_info():
_account_id = request.json['account_id']
_access_key = request.json['access_key']
#data = {'acount_id': _account_id, 'access_key': _access_key}
scan_account(_account_id,_access_key)
#return jsonify(data)
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0', port='443')
Ok lets get a couple of things out the way, I DO NOT suggest you use this for anything other than a local dev. Please use proper SSL.
Make sure you have pyOpenSSL properly installed.
from flask import Flask, jsonify, request, make_response
app = Flask(__name__)
#app.route("/account/",methods=["POST"])
def account_info():
_account_id = request.json['account_id']
_access_key = request.json['access_key']
data = {'acount_id': _account_id, 'access_key': _access_key}
return make_response(jsonify(data), 200)
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0', port='433', ssl_context='adhoc')
I also modified your curl to make it simpler, that and it was causing issues:
curl -X POST -H "Content-Type:application/json" --data '{"account_id":"100002", "access_key":"AKIAWDL6TY5M2INS6J7E"}' https://localhost:9443/account/ --insecure
I get the following output:
{
"access_key": "AKIAWDL6TY5M2INS6J7E",
"acount_id": "100002"
}
This is how i tested it all:
docker run --rm -it -p 9443:443 python:3.7 bash -c '
pip install flask pyOpenSSL;
curl -s https://gist.githubusercontent.com/kingbuzzman/a955b49a318eef9e76b4bf9026cd2595/raw/sample.py > sample.py;
python sample.py'
Here is the gist source: https://gist.github.com/kingbuzzman/a955b49a318eef9e76b4bf9026cd2595
I am trying to learn how to do apis. I copied everything from the book exactly but i am unable to post to the api. I tried posting {'name':'holy'} as raw data in postman( an json posting tool) to api and I get the vladation help message error"No Name provided":but when i try name=holy it works fine. I thought it was not suppose to work like that, How do i get it to work with {'name':'holy'}
from flask import Flask, request,render_template, jsonify
from flask_restful import Resource, Api,marshal_with, fields, reqparse
app = Flask(__name__)
api = Api(app)
class UserApi(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument(
'name',
required=True,
help='No name provided',
location=['form', 'json']
)
def get(self):
return jsonify ({"first_name":"Holy","last_name": "Johnson"})
def post(self):
args = self.reqparse.parse_args()
return jsonify ({"first_name":"Holy","last_name": "Johnson"})
api.add_resource(UserApi, '/users')
if __name__ == '__main__':
app.run(debug=True)
Your code should work - you have to specify the request header Content-Type: application/json. The reason why is because flask-restful's reqparse module tries to parse its data from flask.request.json, which is only set if Content-Type: application/json is set.
If you have access to curl (or wget), you can do the following to test:
$shell> curl -X POST -H "Content-Type: application/json" -d '{"name": "holly"}' http://localhost:5000/users
{
"first_name": "Holy",
"last_name": "Johnson"
}
In Postman, you can set a header, like shown in the screenshot below.