Why is the difference between form submitted from browser and "Requests" when validating SimpleHttpServer

I have a SimleHttpServer with a `do_POST 'function

def do_POST(self):

    print self.path

    form = cgi.FieldStorage(
        fp=self.rfile, 
        headers=self.headers,
        environ={'REQUEST_METHOD':'POST',
                 'CONTENT_TYPE':self.headers['Content-Type'],
        })
    for key in form.keys():
        print key

      

And now the problem: if I submit a request with the browser (HTML form like this)

<form method="post" action="/">
  <input type="text" name="a" value="1"><br>
  <input type="submit" value="Send">
</form>

      

then the values ​​are:

self.path = /
form.keys = [a]

      

If I send the same request with python requests

parameters = {
    "a": 2,
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64)",
    "Content-Type": "application/x-www-form-urlencoded",
    "Referer": "http://127.0.0.1:8001/",
    "Host": "127.0.0.1:8001",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
}

r = requests.post("http://127.0.0.1:8001", params=parameters, headers=headers)

      

values ​​on the server

self.path = /?a=2
form.keys = []

      

Where is the problem? Who cares? I copied the headers from the browser, so everything should be the same.

Thanks in advance for any help or hint.

Working workaround:

If you face this problem, you can use the following workaround in do_POST

(you need to import cgi, urlparse):

    if "?" in self.path:
        qs = self.path.split("?")[1]
        query_dict = dict(urlparse.parse_qsl(qs))
    else:       
        form = cgi.FieldStorage(
            fp=self.rfile, 
            headers=self.headers,
            environ={'REQUEST_METHOD':'POST',
                     'CONTENT_TYPE':self.headers['Content-Type'],
            })
        query_dict = {key: form.getvalue(key) for key in form.keys()}

      

But that is not the answer to the question.

+3


source to share


1 answer


If you want to send data as a POST (that is, not as a GET query string), you must pass it as data

, not params

:

Typically, you want to submit some form-encoded data - like an HTML form. To do this, just pass the dictionary as an argument data

. Your data dictionary will be automatically encoded in the form if a request is made

(Source: More Complex POST Requests )



params

- (optional) Dictionary or bytes to send in the request string for the request.

data

- (optional) Dictionary or list of tuples [(key, value)] (will be formatted), bytes or files an object to send in the request body .

(Source: Main Interface , emphasis mine)

+1


source







All Articles