Trying to implement a flask API with the following code:
import tweepy,flask,os,flask_api,re,json,logging
app = flask.Flask(__name__,template_folder='')
#app.route('/',methods=['POST'])
def answer():
app.logger.info('server responding')
for key,value in flask.request.args.items():
app.logger.info(key+':'+value)
return 'Server on line'
#app.route('/',methods=['GET'])
def home():
return flask.render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)#use_reloader=False
logging.basicConfig(filename='error.log',level=logging.DEBUG)
app.logger.info('Successfull info message')
app.logger.error('Successfull error message')
When I try to curl it wit windows,
curl -X POST -d query=cheese http://127.0.0.1:5000/
(long form)
curl --header "Content-Type: application/json" --request POST --data '{"query":"cheese"}' http://127.0.0.1:5000/
I get
INFO in logtest: server responding
But not a single key/value pair is returned
flask.request.args are URL query parameters.
curl --data is body.
You're sending a request body but expecting them to show up in the URL params. Which will obviously not work.
You need to access request.data instead. There is a convenience method get_json() that you can use to have Flask parse the body into a dictionary for you.
Related
I have a views.py with an endpoint like this:
def endpoint(request):
if request.method == "POST":
body = request.body.decode('utf-8')
body = json.loads(body)
param1 = request.GET.get('param1','default1')
param2 = request.GET.get('param2','default2')
My urls.py have this urlpattern:
url(r'^endpoint$', views.endpoint, name="endpoint")
The problem I have is that if I send requests in one of the following ways it works fine:
curl -X POST http://localhost:8000/endpoint -d #data.json
curl -X POST http://localhost:8000/endpoint?param1=val1 -d #data.json
curl -X POST http://localhost:8000/endpoint?param2=val2 -d #data.json
But if I send a request with both parameters:
curl -X POST http://localhost:8000/endpoint?param1=val1¶m2=val2 -d #data.json
I get the exception:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char
0)
Why I get JSONDecodeError when having multiple parameters? Is it because it's a POST request?
EDIT: I have to use a file data.json because de body of the request is quite big.
I also tried with a smaller json
curl -X POST http://localhost:8000/endpoint?param1=val1¶m2=val2 -d "{"a": "b"}"
To debug I inserted this on the beginning of the code:
print("request body:")
print(request.body)
I get this in the terminal:
request body:
b''
It seems Django don't even receive the request body
in the command line the & means run command in background, try to put url in the double quotes: "http://localhost:8000/endpoint?param1=val1¶m2=val2"
curl -X POST "http://localhost:8000/endpoint?param1=val1¶m2=val2" -d #data.json
I'm setting up a simple rest api using flask and flask-restful. Right now all I'm trying to do is create a post request with some Json data, and then return it just to see if it works. I always get the same error "message": "Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)"
Below is my code
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Tester(Resource):
def get(self):
return {'about': 'Hello World'}
def post(self):
data_json = request.get_json(force=True)
return {'you sent': data_json}
api.add_resource(Tester, '/')
if __name__ == '__main__':
app.run(debug=True)
The curl request I am making to test this is below, I've also tried making request using postman
curl -H "Content-Type: application/json" -X POST -d '{'username':"abc",'password':"abc"}' http://localhost:5000
You need to select raw -> JSON (application/json) in Postman like this:
When it comes to your cURL request, answer explains that windows's command line lacks support of strings with single quotes, so use:
curl -i -H "Content-Type: application/json" -X POST -d "{\"username\":\"abc\", \"password\":\"abc\"}" 127.0.0.1:5000
instead:
curl -H "Content-Type: application/json" -X POST -d '{'username':"abc",'password':"abc"}' http://localhost:5000
\ escapes " character.
You also need to have the Content-Length header enabled.
Some additional information in case you are using python script to test your flask api like me - you have to dumps before adding the dictionary to the data field.
import requests
import json
response = requests.post(
'http://localhost:5000',
data = json.dumps({'username':"abc",'password':"abc"}),
headers = {"Content-Type": "application/json"}
)
The curl request (payload) is incorrect. Use double quotes in the payload.
curl -H "Content-Type: application/json" -X POST -d '{"username":"abc","password":"abc"}' http://localhost:5000
I am trying to integrate the Flask-RESTful's request parsing interface, reqparse in my backend to request HTTP headers from the client. Currently, I wish to use this for authentication of a user and wish to pass 'secret_key' in HTTP headers.
The function I am using for this task is the add_argument() function. My code for requesting the header is as follows:
reqparse = reqparse.RequestParser()
reqparse.add_argument('secret_key', type=str, location='headers', required=True)
However, on sending the following cURL request:
curl -H "Content-Type: application/json" -H "{secret_key: SECRET}" -X POST -d '{}' http://localhost:5000/authUser
I recieve the following 400 error on my Pycharm Community edition editor :
127.0.0.1 - - [02/Aug/2016 18:48:59] "POST /authUser HTTP/1.1" 400 -
and the following message on my cURL terminal:
{
"message": {
"secret_key": "Missing required parameter in the HTTP headers"
}
}
To reproduce this error on Pycharm (and hopefully all other compilers as well), please use the files written below as follows:
Folder - Sample_App
- __init__.py
- run.py
- views.py
__init__.py
from flask import Flask
from flask_restful import Api
from views import AuthUser
app = Flask(__name__)
api = Api(app)
api.add_resource(AuthUser, '/authUser')
views.py
from flask_restful import reqparse, Resource
class AuthUser(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('secret_key', type=str, location='headers', required=True)
def post(self):
data = self.reqparse.parse_args()
if data['secret_key'] == "SECRET":
print("Success")
return 200
return 400
run.py
from __init__ import app
app.run(host='0.0.0.0', port=5000, debug=True)
Could you please tell me how to fix this issue? I want to know if the location parameter needs to be changed or if there is something wrong in my cURL request.
EDIT:
With the help of Methika's response, I have figured out the error. The add_argument() function does not take _ in a headers parameter. However, when I use the requests.headers['secret_key'] function, I am able to request headers with the _ character just fine. Why is that the case?
New Code of views.py:
views.py
from flask_restful import reqparse, Resource
class AuthUser(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
def post(self):
data = self.reqparse.parse_args()
data['secret_key'] = request.headers['secret_key']
if data['secret_key'] == "SECRET":
print("Success")
return 200
return 400
I did some tests with the code you gave here and I found out that the problem doesn't come from you code but from the name of the variable:
If you replace secret_key by secretkey (or something else without underscore) it will work !
I found this post, flask seems to not accept underscores in header variable names.
Instead of this curl request
curl -H "Content-Type: application/json" -H "{secret_key: SECRET}" -X POST -d '{}' http://localhost:5000/authUser
Try this one
curl -H "Content-Type: application/json" -H "secret_key: SECRET" -X POST -d '{}' http://localhost:5000/authUser
In header normally I have seen using value like "Key: Value"
I have a Flask app that uses Celery to run tasks. To start the environment I start a redis server (to store results), then Celery, then my app (python app.py). To kick off a job, I want to issue a POST request with cURL, and I want to pass in a parameter, which will be stored in the key-value:
curl ... -X POST -d '{"key": "value"}'
How does my Python program receive that parameter? Normally you'd use argv when you're just running python app.py, but that doesn't seem to work.
You would curl to the address with post variables.
app.py would try to parse if the request type is POST AND to parse the post variables.
post request
curl ... -X POST -d '{"type": "sendemail","who":"foo#bar.42"}'
curl ... -X POST -d '{"type": "sendsms","who":"+1297581234"}'
app.js (I don't know flask)
if request.type == 'POST':
if post['type'] == 'sendemail':
celery.createjob('sendemail',post['who'])
elif post['type'] == 'sendsms'
celery.createjob('sendsms',post['who'])
learn more about flask and refer to this SO question
If you want to make a POST request, then you can use requests.post()
While on the receiving end. You can use request object provided by flask.
For example:
On the client end:
from requests import post
import json
payload = {'product_id': 'B014F6U5N6', 'website_name': 'amazonIN', 'url': 'xyz'}
r = post("http://localhost:5000", json.dumps(payload), headers={'Content-Type': 'application/json'})
print r.text
On the receiving end:
from flask import request
product_id = request.json['product_id']
url = request.json['url']
website_name = request.json['website_name']
I am attempting to do a basic request on my Flask-app with cUrl.
This is my Flask code:
#application.route('/fb_checkin/', methods=['POST'])
def checkin():
qr_code = request.form['qr']
provider_name = request.form['provider']
#Lookup Access Key by qr in database
resp = requests.post("https://<USERNAME>:<PASSWORD>#<DOMAIN>.cloudant.com/socialmattic_users/_find",
'{"selector": {"qr": "' + qr_code + '"}}')
token = resp.json()['fb_access_token']
This is my curl command:
curl -X POST 'localhost:5000/fb_checkin/?qr=default&provider=void'
After issuing the curl command an HTTP 400 error is returned.
Is anyone able to tell me why this is the case?
Thanks for any help.
curl should be and also no quotes to URL
curl --data "qr=default&provider=void" http://localhost:5000/fb_checkin/