web-dev-qa-db-fra.com

Python Falcon - obtenir POST Les données

J'essaie d'utiliser le paquetage falcon dans mon projet. Le problème est que je n'ai pas trouvé de moyen d'obtenir les données de corps de la demande de publication HTTP.

J'ai utilisé le code de l'exemple, mais req.stream.read() ne renvoie pas JSON comme prévu.

Le code est:

raw_json = req.stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')

Comment obtenir les données POST?

Merci pour toute aide

5
Gomi

Une petite exploration du problème a conduit au problème lié suivant sur github . Il indique que falcon framework au moins dans sa version 0.3 et que Python 2 est utilisé n’a pas analysé les données 'POSTed' en tant que chaîne si elles ont été correctement échappées. Nous pourrions utiliser davantage d'informations sur les données que vous essayez d'envoyer via la demande POST] et dans quel format est-il envoyé, comme s'il était envoyé sous forme de texte simple, ou avec un en-tête Content-Type: application/json , ou si cela passe par un formulaire HTML.

Bien que la question exacte ne ressorte pas clairement de la question, je pourrais toujours suggérer d'essayer d'utiliser bounded_stream au lieu de stream comme suit:

raw_json = req.bounded_stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')

pour la documentation officielle suggère l'utilisation de bounded_stream lorsque des conditions incertaines telles que Content-Length indéfini ou 0, ou si les informations d'en-tête sont totalement absentes.

bound_stream est décrit comme suit dans la documentation officielle falcon .

Encapsuleur semblable à un fichier autour du flux pour normaliser certaines différences entre les objets d’entrée natifs employés par différents serveurs WSGI. Bounded_stream est notamment conscient de la longueur de contenu attendue du corps et ne bloque jamais les lectures en dehors des limites, en supposant que le client ne se bloque pas lors de la transmission des données au serveur.

Falcon reçoit les données des demandes HTTP sous forme d’objet tampon, telles qu’elles ont été transmises par l’encapsuleur WSGI qui reçoit les données du client. Il est également possible qu’elles ne soient pas analysées correctement au-dessus des données pour les convertir en une structure de données plus utilisable pour des raisons de performances. 

6
Shubham Mishra

Jusqu'ici ... pour moi, bounded_stream.read () et stream.read () obtiennent tous deux les données postées sous forme de type str. Je n'ai trouvé qu'un moyen de contourner le problème jusqu'à présent:

def on_post(self, req, resp):
    posted_data = json.loads(req.stream.read())
    print(str(type(posted_data)))
    print(posted_data)

Le chargement de la chaîne dans un json dict une fois que les données postées sont reçues est la seule solution que je puisse trouver

1
kittyboo

J'ai ajouté des modifications dans request.py dans le cadre falcon pour analyser application/x-www-form-urlencoded et multipart/from-data . J'ai soulevé la demande d'extraction - https://github.com/falconry/ falcon/pull/1236 mais il n’a pas encore été fusionné dans master ..__ Vérifiez-le - https://github.com/branelmoro/falcon

J'ai ajouté un nouveau code pour analyser POST, PUT et DELETE application/x-www-form-urlencoded et multipart/form-data . Les champs de texte seront disponibles dans le dictionnaire req.form_data et le flux de mémoire tampon de fichier sera disponible dans dictionnaire req.files.

J'espère que cela aidera à accéder à POST et aux paramètres GET séparément et que nous pourrons également télécharger des fichiers ..___ Une bonne chose à propos du changement est qu'il ne chargera pas l'intégralité du fichier téléchargé en mémoire.

Vous trouverez ci-dessous un exemple de code montrant comment utiliser les applications POST, PUT et DELETE application/x-www-form-urlencoded et multipart/form-data:

import falcon

class Resource(object):

    def on_post(self, req, resp):

        # req.form_data will return dictionary of text field names and their values
        print(req.form_data)

        # req.form_data will return dictionary of file field names and
        # their buffer class FileStream objects as values
        print(req.files)

        # support we are uploading a image.jpg in `pancard` file field then
        # req.files["pancard"] will be FileStream buffer object

        # We can use set_max_upload_size method to set maximum allowed
        # file size let say 1Mb = 1*1024*1024 bytes for this file

        req.files["pancard"].set_max_upload_size(1*1024*1024)

        # We can use uploadto method to upload file on required path (Note: absolute filepath is required)
        # This method returns boolean - `True` on successful upload
        # and if upload is unsuccessful then it returns `False` and sets error on failure.
        path = "/tmp/" + req.files["pancard"].name

        response = req.files["pancard"].uploadto("/tmp/" + path)

        print(response)

        # Once file is uploaded sucessfully, we can check it's size
        print(req.files["pancard"].size)

        # If file is not uploaded sucessfully, we can check it's error
        print(req.files["pancard"].error)

        resp.body = "Done file upload"

        resp.status = falcon.HTTP_200

# falcon.API instances are callable WSGI apps
app = falcon.API()

things = Resource()

# things will handle post requests to the '/post_path' URL path
app.add_route('/post_path', things)

Faites-moi savoir si vous avez des doutes.

1
Branel Moro

Un grand merci à Ryan (et Prateek Jain) pour la réponse.

La solution consiste simplement à mettre app.req_options.auto_parse_form_urlencoded=True. Par exemple:

import falcon

class ThingsResource(object):
    def on_post(self, req, resp):
        value = req.get_param("value", required=True)
        #do something with value

app = falcon.API()
app.req_options.auto_parse_form_urlencoded=True

things = ThingsResource()

app.add_route('/things', things)
0
Zezombye