web-dev-qa-db-fra.com

Accès aux données POST entrantes dans Flask

Voici le code flask:

from flask import Flask, request
import json
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def refresh():
    params = {
        'thing1': request.values.get('thing1'),
        'thing2': request.values.get('thing2')
    }
    return json.dumps(params)

Voici le cURL:

$ curl -XGET 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}'                                              
> {"thing1": "1", "thing2": null}

$ curl -XGET 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}'                                              
> {"thing1": "1", "thing2": null}

Le docs semble TRÈS clair que cela devrait fonctionner:

forme

Un MultiDict avec les données de formulaire analysées de POST ou requêtes PUT. N'oubliez pas que les téléchargements de fichiers ne se termineront pas ici, mais plutôt dans l'attribut files.

args

Un MultiDict avec le contenu analysé de la chaîne de requête. (La partie de l'URL après le point d'interrogation).

valeurs

Un CombinedMultiDict avec le contenu du formulaire et des arguments.

Des idées sur ce que je fais mal?

Mise à jour: Essayer les suggestions d'une des réponses, échanger la ligne return:

L'utilisation de return json.dumps(json.load(request.body.decode("utf-8") )) génère l'erreur AttributeError: 'Request' object has no attribute 'body'

L'utilisation de return json.dumps(json.load(request.json)) génère l'erreur AttributeError: 'NoneType' object has no attribute 'read'

L'utilisation de POST avec le code d'origine semble n'avoir aucun effet:

$ curl -XPOST 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}'
{"thing1": "1", "thing2": null}

La définition du type de contenu et l'utilisation de POST avec le code d'origine n'a également aucun effet apparent:

$ curl -XPOST -H "Content-Type: application/json" 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}' 
{"thing1": "1", "thing2": null}

même si je suis allé et vérifié que le type de contenu était alors correctement défini:

...
print(request.headers)
...

Host: 127.0.0.1:5000
User-Agent: curl/7.54.0
Accept: */*
Content-Type: application/json
Content-Length: 12
5
Narfanator

Vous envoyez par inadvertance le mauvais Type de conten .

Par défaut, l'indicateur -d De curl enverra POST données avec le type de contenu application/x-www-form-urlencoded . Puisque vous ' ne pas envoyer de données dans le format attendu ( clé = valeur ), il abandonne complètement les données. Pour les données JSON, vous devrez envoyer la requête HTTP avec le type de contenu défini sur application/json comme ceci:

curl -XPOST -H "Content-Type: application/json" 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}'

De plus, le champ request.form Du flacon contient uniquement données du formulaire POST , pas d'autres types de contenu. Vous pouvez accéder au corps de requête brut POST avec request.data ou, plus commodément, aux données JSON analysées à l'aide de request.get_json .

Voici une version fixe de votre exemple:

from flask import Flask, request
import json
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def refresh():
    params = {
        'thing1': request.values.get('thing1'),
        'thing2': request.get_json().get('thing2')
    }
    return json.dumps(params)


app.run()

MISE À JOUR: J'ai mal parlé plus tôt - request.body Devrait en fait être request.data. De plus, il s'avère request.json Est déconseillé et request.get_json Devrait être utilisé maintenant à la place. Le message d'origine a été mis à jour.

6
jtimmons