geopython / pywps

PyWPS is an implementation of the Web Processing Service standard from the Open Geospatial Consortium. PyWPS is written in Python.
https://pywps.org
MIT License
178 stars 117 forks source link

Possible bug on POST request with json input #661

Closed jbeilin closed 2 years ago

jbeilin commented 2 years ago

Description

I developed 2 processes with pyWps. The first one works with a GET request but the second (identifier = "alti") needs a POST request because I need to send some heavy data to the process. I am trying to use a json input with my request.

Here is the request :

import requests
import json

url = 'http://127.0.0.1:3000/wps'
S = {
     "identifier": "alti",
     "operation": "execute",
     "inputs": {"points": [ (5, 44.5) , (6.5 , 44.6), (6.2,45.3)], "datum":"epsg:4326"}
}

S = json.dumps(S)
headers = {'Content-type': 'application/json'}
x = requests.post(url, json=S, headers=headers)

As this I got no answer. I had a look in pywps/app/WPSRequest.py with a few changes around line 130 :

       if not json_input:
            try:
                doc = etree.fromstring(self.http_request.get_data())
            except Exception as e:
                raise NoApplicableCode(str(e))
            operation = doc.tag
            version = get_version_from_ns(doc.nsmap[doc.prefix])
            self.set_version(version)

            language = doc.attrib.get('language')
            self.check_and_set_language(language)

            request_parser = self._post_request_parser(operation)
            request_parser(doc)
        else:
            print("json_input")
            try:
                s = self.http_request.get_data()
                print("1", s, type(s))
                jdoc = json.loads(s)
                print("2", jdoc, type(jdoc))
                jdoc = json.loads(jdoc) # I added this line which seems to be necessary
                print("3", jdoc, type(jdoc))
            except Exception as e:
                raise NoApplicableCode(str(e))

In the terminal window I get the following : 1 b'"{\"identifier\": \"alti\", \"points\": [[4, 67], [6, 87]]}"' <class 'bytes'> 2 {"identifier": "alti", "points": [[4, 67], [6, 87]]} <class 'str'> 3 {'identifier': 'alti', 'points': [[4, 67], [6, 87]]} <class 'dict'> It works as soon as I put 2 json.loads(). The fist one only gives a string, not a dictionnary.

May be I am doing something wrong in my request but it looks strange.

Environment

Steps to Reproduce

Additional Information

Regards

gschwind commented 2 years ago

Hello,

I think you are misusing requests.post, you should put S variable without serialising it as str. I guess also that request.post will setup the content type properly.

Best regards

jbeilin commented 2 years ago

Hello,

Ok, great. Thank you.

import requests

pts = [[6.4933795, 44.86910549999999], [6.4937965, 44.875577899999996], [6.488739000000001, 44.880840199999994], [6.4904189, 44.89242469999999], [6.4992149, 44.89410989999996], [6.500417700000001, 44.8994457]]
url = 'http://127.0.0.1:3000/wps'
S = {
     "identifier": "alti",
     "operation": "execute",
     "inputs": {"points": pts, "datum":"EPSG:4326"}
     }

headers = {'Content-type': 'application/json'}
x = requests.post(url, json=S, headers=headers)