reznov11
reznov11

Reputation: 153

Why i am getting 400 Bad Request error when sending json data in Flask?

I am trying to write a small restful api application, i am using Chrome Postman extension for sending requests to the app .

I believe that my code does not have mistakes but every time i am sending post request a 400 Bad Request error raising , here is my code:

@api_route.route('/api', methods=['GET'])
def api():
    return jsonify({'message':'Api v1.0'})

@api_route.route('/api', methods=['POST'])
def create_user():
    data = request.get_json()
    if data:
        hashed_password = generate_password_hash(data['password'], method='sha256')
        api = Api(email=data['email'], password=hashed_password)
        db.session.add(api)
        db.session.commit()
        return jsonify({'message', 'New User Created!'})

The json data that i am sending looks like this:

{"email" : "Test", "password" : "123123123"}

Why i am getting the 400 error ??

Update:

Screenshots for the requests using Postman:

GET Request GET Request

POST Request POST Request

Here i am initiating api route inside api controller :

from flask import Blueprint
api_route = Blueprint(
    'api',
    __name__
)
from . import views

then i am registering it inside def create_app() function :

from .api import api_route
app.register_blueprint(api_route)

Here are the extensions that i am using in my application:

toolbar = DebugToolbarExtension()
assets_env = Environment()
cache = Cache()
moment = Moment()
htmlminify = HTMLMIN()
csrf = CSRFProtect()
jac = JAC()
googlemap = GoogleMaps()
session = Session()
principal = Principal()

Upvotes: 1

Views: 3530

Answers (3)

Alan B
Alan B

Reputation: 4288

A note for anyone else experiencing this with PostMan and Flask - you will also hit a HTTP 404 if your URL in PostMan is HTTPS but your Flask app only handles HTTP.

Upvotes: 0

reznov11
reznov11

Reputation: 153

I solved the problem, i've initiated CSRFProtect with app so i need to include X-CSRFToken in all my requests, so i have two choices:

1 - To include the csrf_token in request.headers for all the requests

2 - Using @csrf.exempt decorator that coming with flask_wtf.csrf

For now i am using @csrf.exempt, so it become like this:

@api_route.route('/api', methods=['GET','POST'])
@csrf.exempt
def create_user():
    if request.method == 'GET':
        return jsonify({'message' : 'API v1.0'})
    elif request.method == 'POST':
        data = request.get_json()
        hashed_password = generate_password_hash(data['password'], method='sha256')
        new_user_api = Api(email=data['email'], password=hashed_password)
        db.session.add(new_user_api)
        db.session.commit()
        return jsonify({'message' : 'New user created!'})
    return return jsonify({'message' : 'No user has been added!'})

Thanks for @MrPyCharm for his interests , salute :) .

Upvotes: 2

Ahmed Dhanani
Ahmed Dhanani

Reputation: 861

A good approach would be to structure your views as follows:

Instead of creating view with same route for different request methods, you can handle the request methods in the same view:

@api_route.route('/api', methods=['GET', 'POST'])
def api():
    if request.method == 'GET':
        return jsonify({'message':'Api v1.0'})

    else:
        data = request.get_json(force=True)
        if data:
            hashed_password = generate_password_hash(data['password'], method='sha256')
            api = Api(email=data['email'], password=hashed_password)
            db.session.add(api)
            db.session.commit()
            return jsonify({'message': 'New User Created!'})

        # Just in case the if condition didn't satisfy
        return None

Upvotes: 1

Related Questions