'Always getting "POST http://127.0.0.1:5000/product net::ERR_ABORTED 400 (BAD REQUEST)" when doing a POST with fetch to Flask REST API

I'm always getting the error "POST http://127.0.0.1:5000/product net::ERR_ABORTED 400 (BAD REQUEST)" when I try to do a POST request with fetch in JavaScript to a Flask REST API (when I try to do with GET it works).

This is the code I'm using:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script type="application/javascript">
    fetch('http://127.0.0.1:5000')
    .then((res) => res.json())
    .then((data) => console.log(data));

    fetch('http://127.0.0.1:5000/product', {
        mode: 'no-cors',
        method: 'POST',
        headers: {
            'Content-type' : 'application/json'
        },
        body: JSON.stringify({
            name: 'Product 5',
            description: 'This is product one',
            price: 350.80,
            qty: 100
        })
    })
    .then((res) => res.json())
    .then((data) => console.log(data));
  </script>
</body>
</html>

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_cors import CORS, cross_origin
import os

# Init app
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'

basedir = os.path.abspath(os.path.dirname(__file__))
# Database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'db.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # this line prevents a warning to show up in the console
# Init db
db = SQLAlchemy(app)
# Init ma
ma = Marshmallow(app)

# Product Class/Model
class Product(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(100), unique=True)
  description = db.Column(db.String(200))
  price = db.Column(db.Float)
  qty = db.Column(db.Integer) #quantity

  def __init__(self, name, description, price, qty):
    self.name = name
    self.description = description
    self.price = price
    self.qty = qty

# Product Schema
class ProductSchema(ma.Schema):
  class Meta: # fields that we are allow to show 
    fields = ('id', 'name', 'description', 'price', 'qty')

# Init schema
product_schema = ProductSchema() # strict=True prevents a warning to show up in the console
products_schema = ProductSchema(many=True)

# Create a Product
@app.route('/product', methods=['POST'])
@cross_origin()
def add_product():
  name = request.json['name']
  description = request.json['description']
  price = request.json['price']
  qty = request.json['qty']

  new_product = Product(name, description, price, qty)

  db.session.add(new_product)
  db.session.commit()

  return product_schema.jsonify(new_product)

@app.route('/', methods=['GET'])
@cross_origin()
def get():
  return jsonify({'msg': 'Hello World'})

# Run Server
if __name__ == '__main__':
  app.run(debug=True)

I'm think it's a problem with the JavaScript code, because I tried to make a POST with Postman Desktop Application and it worked:

Postman App Image



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source