james kaly
james kaly

Reputation: 47

Python 3 Requests - How to make a post request, fill in forms and submit

In a website with this code from flask:

from flask import Flask, request

app = Flask(__name__)


@app.route('/upload', methods=["POST", "GET"])
def upload():
    return """
        <html>
          <body>
            <h1>Guess what! I am a title!</h1>
              <form action="/run" method="POST" name="upload">
                <input type="password" name="password">
                <input type="file" name="file" />
              </form>
          </body>
        </html>"""


@app.route('/run', methods=["POST"])
def download_file():
    if request.form['password'] == 'hey':
        request.files['file'].save('/home/james/site.txt')
        return "File uploaded successfully!"
    else:
        return "Wrong password"

How can I run a proper post request and get the output of /run? So far I've tried:

upload = {'password': 'whatever',
          'file': open(my_files_location, 'rb')}
r = requests.post('http://jamesk.pythonanywhere.com/upload', data=upload)

But the website neither has run the form nor did it return what I wanted. This is what I get when I run r.content:

b'\n        <html>\n          <body>\n            <h1>Guess what! I am a title!</h1>\n              <form action="/run" method="POST" name="upload">\n                <input type="password" name="password">\n                <input type="file" name="file" />\n              </form>\n          </body>\n        </html>'

When I expected b'Wrong password'

Upvotes: 0

Views: 9321

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121554

You are posting to the form path, not the form handler path. Your browser reads the action="/run" attribute on the form and uses that as the target to post to. You need to do the same:

url = 'http://jamesk.pythonanywhere.com/run'

Note that the URL ends in /run, not /upload.

Next, you need to fix your form handling; you need to configure the form to use the right mimetype and use the files option to upload files in requests:

@app.route('/upload', methods=["POST", "GET"])
def upload():
    return """
        <html>
          <body>
            <h1>Guess what! I am a title!</h1>
              <form action="/run" method="POST" name="upload" enctype="multipart/form-data">
                <input type="password" name="password">
                <input type="file" name="file" />
              </form>
          </body>
        </html>"""

and

r = requests.post(url, 
    data={'password': 'hey'}, 
    files={'file': open(my_files_location, 'rb')})

Upvotes: 1

Related Questions