Cant receive Post Data to gcloud flask api from fetch function in react app

Question:

I have a very simple api that is written in Flask and deployed to cloud cloud run.
I am collecting data from the client and passing it to a cloud run flask api, and once flask receives the post request json object, it needs to restructure the data and send it to a third-party payment processing app.
I’m a MERN developer, don’t really know python, just REST and HTTP so Ive been debugging for days and im absolutely stuck. any help would be awesome.
here is my react fetch request:

    let items = [];
    cartItems.forEach((cartItem) => {
      let itemObject = {
        strainTitle: cartItem.title,
        quantity: cartItem.quantity,
      };
      items.push(itemObject)
    });

    let orderSummary = {
      total: total + shipping + tax,
      s1,
      s2,
      fname: firstName,
      lname: lastName,
      phone: phoneNumber,
      memo: `confirmation email sent to ${email}`,
      email,
      city,
      state: stateOfResidence,
      addy,
      zipcode: zipCode,
      items,
    };

    const options = {
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      method: "POST",
      mode: "cors",
    };
    options.body = JSON.stringify(orderSummary)

    fetch(
      process.env.REACT_APP_SEAMLESS_URL,
      options
    )
      
      .then((response) => response.body)
      .then((body) => {
        const reader = body.getReader();

        return new ReadableStream({
          start(controller) {
            return pump();

            function pump() {
              return reader.read().then(({ done, value }) => {
                // When no more data needs to be consumed, close the stream
                if (done) {
                  controller.close();
                  return;
                }

                // Enqueue the next data chunk into our target stream
                controller.enqueue(value);
                return pump();
              });
            }
          },
        });
      })

      .then((stream) => new Response(stream))
      .then((response) => {
        if (response.status === 200) {
          clearCart();
          history.push("/");
        }
      });

    // { type: "POST", data: cart }).then(response => console.log(response))
  };

and here is my app.py:

def index(path):
        # GET request
        if request.method == 'GET':
                   return {
        "loaded": True,
        "val": "Flask Api running in the cloud"
        }
        # POST request
        if request.method == 'POST':
                data = request.get_json(force=True)
                total = data.get("orderSummary").get("total")
                r = data.get("orderSummary").get("s1")
                ac = data.get("orderSummary").get("s2")
                fname =data.get("orderSummary").get("fname")
                lname = data.get("orderSummary").get("lname")
                memo = data.get("orderSummary").get("memo")
                city = data.get("orderSummary").get("city")
                state = data.get("orderSummary").get("state")
                zipcode = data.get("orderSummary").get("zipcode")
                addy = data.get("orderSummary").get("addy")
                email = data.get("orderSummary").get("email")
                items = data.get("orderSummary").get("items")
                phone_number = data.get("orderSummary").get("phone")
                logging.info(data)
                logging.info(total, r, ac, fname, lname, memo, city, state, zipcode, addy, email, items, phone_number)

                app.config.from_pyfile('./settings.py')
                load_dotenv('.env')
                url = 'https://sandbox.seamlesschex.com/v1/check/create'
                payload = json.dumps({
                        "number": random.randint(1,999999), 
                "email": email, 
                "authorization_date": date.today(), 
                        "label": "Thank you from Chubby's",
                        "address": addy,
                        "city": city,
                        "state": state,
                        "zip": zipcode,
                        "phone": phone_number,
                        "bank_account": ac,
                        "bank_routing": r,
                        "name": fname + " " + lname,
                        "memo": memo,
                        "amount": total,
        }, separators=(',', ':'), default=str)

                headers = {
                        'Content-Type': 'application/json',
                        'Authorization': app.config.get("SEAMLESS_SANDBOX_KEY")
                        }

                response = requests.request('POST', url, headers = headers,
                data = payload, allow_redirects=False, timeout=1000000000)
                data = response.json()
                checkDATA = data['check']
                if checkDATA:
                        from flask import Flask, jsonify
                        from flask_mail import Mail, Message

                        mail_settings = {
                        "MAIL_SERVER": app.config.get("EMAIL_SERVER"),
                        "MAIL_PORT": 465,
                        "MAIL_USE_TLS": False,
                        "MAIL_USE_SSL": True,
                        "MAIL_USERNAME": app.config.get("EMAIL_ACCT"),
                        "MAIL_PASSWORD": app.config.get("EMAIL_PWD")
                        }
                        app.config.update(mail_settings)
                        mail = Mail(app)
                        with app.app_context():
                                msgToCustomer = Message(subject="Successful Order Initiation With Chubbys Seed Supply Co.", sender=app.config.get("EMAIL_ACCT"), recipients=[email], body="The Biggest Chubbys' thank you is sent to you today. We recived your order today and are dilligently processing your order and getting it all packaged up nice and neat and safe. Be on the lookout in your inbox for an email with the traking number. We'll send you an email with the tracking number once the Post Office has your package and it's on the way :). Thank you and have a great day. ")
                                mail.send(msgToCustomer)
                                msgToChubbys = Message(subject="NEW_ORDER_NEEDS TO BE FULLFILLED", sender=app.config.get("EMAIL_ACCT"), recipients=[app.config.get("EMAIL_ACCTT")], body=f"New order for {fname} {lname}. The order total is {total} and the order consists of the following items {items}. Send to {addy} {city} {state} {zipcode}. Send tracking number to {email} ")
                                mail.send(msgToChubbys)
                        return json.dumps(checkDATA)

here is the error im receiving in google cloud:
File "/app/app.py", line 39, in index total = data.get("orderSummary").get("total") AttributeError: 'NoneType' object has no attribute 'get'

Asked By: Robert Zobrist

||

Answers:

Your Python code is attempting to read in the data from your front-end as if it were in this shape:

{
    "orderSummary": {
        "total": ...,
        "s1": ...,
        "s2": ...,
        ...
    }
}

However, the data you are sending looks as if it is in this shape:

{
    "total": ...,
    "s1": ...,
    "s2": ...,
    ...
}

Note that there is no orderSummary property in the top-level object, so data.get("orderSummary") will return None, and so calling .get(...) on that will give you the error AttributeError: 'NoneType' object has no attribute 'get'.

Try removing all of the calls to .get("orderSummary"):

                total = data.get("total")
                r = data.get("s1")
                ac = data.get("s2")
                # and similarly for other lines...

I note also you have a line logging.info(data), below all of the lines that pull values out of data. That’s maybe not the most useful place for it, because if data isn’t in the shape you expect it to be, it’s likely that an exception will be raised before the logging line is reached and so you don’t find out what shape the data is actually in. Instead, try logging data just after you receive it: that way, you can see the exact shape of the data you’re getting, regardless of whether it’s as you expect.

Answered By: Luke Woodward