21

I am having trouble reading a POST request with bottle.py.

The request sent has some text in its body. You can see how it's made here on line 29: https://github.com/kinetica/tries-on.js/blob/master/lib/game.js.

You can also see how it's read on a node-based client here on line 4: https://github.com/kinetica/tries-on.js/blob/master/masterClient.js.

However, I haven't been able to mimic this behavior on my bottle.py-based client. The docs say that I can read the raw body with a file-like object, but I can't get the data neither using a for loop on request.body, nor using request.body's readlines method.

I'm handling the request in a function decorated with @route('/', method='POST'), and requests arrive correctly.

Thanks in advance.


EDIT:

The complete script is:

from bottle import route, run, request

@route('/', method='POST')
def index():
    for l in request.body:
        print l
    print request.body.readlines()

run(host='localhost', port=8080, debug=True)
Martín Coll
  • 3,368
  • 3
  • 37
  • 52
  • I thought it was needed to rewind the `StringIO` object, but it is not necessary. Could you add the Python functions to your question? – A. Rodas Feb 20 '13 at 20:44
  • How do you know that requests arrive correctly? What is the output and/or traceback for the code that you have shown here? – John Y Feb 20 '13 at 22:15
  • Bottle prints on console a 200 status code each time I make a request. I have also debugged the application with Eclipse/PyDev, and the execution breaks on breakpoints correctly. – Martín Coll Feb 20 '13 at 22:18
  • So are you saying that you aren't getting any errors, and `request.body` appears to be empty? (So the `for` loop prints nothing, and your second `print` statement prints `[]`?) – John Y Feb 21 '13 at 14:31
  • @tinchou Could you provide a bit more details on the request? (it is not so easy to start up the application and hunt for these details). Simple way to provide needed details would be to run your app (in node.js), open it Chrome, start up Developer Tools (press F12) and in Network tab find the request which you are trying to do with bottle. Right click on the request and from context menu pick `Copy All as HAR`. This places into clipboard JSON file, describing the request. Add it to your question and we will know all the details about your request to serve by bottle app. – Jan Vlcinsky Jun 04 '14 at 12:17
  • OK, I'll do it if I have some spare time! It's not important anymore, but I'd like to solve this issue :). – Martín Coll Jun 04 '14 at 17:12

2 Answers2

20

Did you try simple postdata = request.body.read() ?

Following example shows reading posted data in raw format using request.body.read()

It also prints to the log file (not to the client) raw content of body.

To show accessing of form properties, I added returning "name" and "surname" to the client.

For testing, I used curl client from command line:

$ curl -X POST -F name=jan -F surname=vlcinsky http://localhost:8080

The code which works for me:

from bottle import run, request, post

@post('/')
def index():
    postdata = request.body.read()
    print postdata #this goes to log file only, not to client
    name = request.forms.get("name")
    surname = request.forms.get("surname")
    return "Hi {name} {surname}".format(name=name, surname=surname)

run(host='localhost', port=8080, debug=True)
evandrix
  • 6,041
  • 4
  • 27
  • 38
Jan Vlcinsky
  • 42,725
  • 12
  • 101
  • 98
7

Simple script for processing POSTed data. POSTed data are written in a terminal and returned to the client:

from bottle import get, post, run, request
import sys

@get('/api')
def hello():
    return "This is api page for processing POSTed messages"

@post('/api')
def api():
    print(request.body.getvalue().decode('utf-8'), file=sys.stdout)
    return request.body

run(host='localhost', port=8080, debug=True)

Script for POSTing json data to the script above:

import requests
payload = "{\"name\":\"John\",\"age\":30,\"cars\":[ \"Ford\", \"BMW\",\"Fiat\"]}"
url = "localhost:8080/api"
headers = {
  'content-type': "application/json",
  'cache-control': "no-cache"
  }
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
Warf
  • 301
  • 2
  • 9