Search code examples
pythonjsonflaskpython-requestshttp-status-code-400

Json in PUT request to Python Flask app fails to decode


I'm working on building an SQLite3 database to store aperture flux measurements of stars in any given astronomical image. I have one file (star_database.py) containing a Flask app running with two routes that handle selecting from and inserting into that database. There is a separate script (aperture_photometry.py) that will call those routes when incoming images need photometric processing. The crux of my problem is in the interaction between the function to insert data into the SQLite database and the aperture photometry script tasked with passing data to the Flask app. Here are the relevant functions:

# Function in aperture_photometry.py that turns Star object data into a dictionary
# and passes it to the Flask app

from astropy.io import fits
import requests
import json

def measure_photometry(image, bandpass):
    df = fits.getdata(image)
    hf = fits.getheader(image, ext=1)
    date_obs = hf['DATE-OBS']
    ra, dec = get_center_coords(hf)
    response = requests.get(f'http://127.0.0.1:5000/select/{ra}/{dec}/').content
    star_json = json.loads(response)
    if star_json is not None:
        stars = json_to_stars(star_json)
        get_raw_flux(df, df*0.01, hf, stars) # Error array will be changed
        star_json = []

        # Critical section
        for star in stars:
            star_json.append({"star_id":star.star_id, "source_id":star.source_id, "flux":star.flux, "flux_err":star.flux_err})
        response = requests.put('http://127.0.0.1:5000/insert/', data={'stars':star_json, 'bandpass':bandpass, 'dateobs':date_obs})
        print(response.content)
    else:
        print("ERROR: Could not get star objects from database.")
# Function in star_database.py that handles incoming flux measurements from the 
# aperture photometry script, and then inserts data into the SQLite database

from flask import Flask, request

@app.route('/insert/', methods=['PUT'])
def insert_flux_rows():
    conn = create_connection(database)
    if conn is not None:
        c = conn.cursor()
        body = request.get_json(force=True)
        print(body)
        
        # More comes after this, but it is not relevant to the question

After running the Flask app and calling aperture_photometry.py, the PUT request response.content line prints a 400 Bad Request error with the message, Failed to decode JSON object: Expecting value: line 1 column 1 (char 0). I think that problem is either in the way I have tried to format the star object data as it is being passed into the PUT request in measure_photometry, or if not there is something wrong with doing body = request.get_json(force=True). It is also worth mentioning that the statement print(body) in insert_flux_rows does not print anything to stdout. For all intents and purposes the two scripts must remain separate, i.e. I cannot combine them and remove the requests dependency.

I would really appreciate some help with this, as I have been trying to fix it all day.


Solution

  • Based on the top answer from this question, it seems like your data variable in the measure_photometry function may not be properly convertable to json.

    You should try to test it out (maybe run a json.dumps on it) to see if a more detailed error message is provided. There's also the jsonschema package.