0

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'

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
james kaly
  • 47
  • 1
  • 3
  • 6

1 Answers1

1

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')})
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • With the code in my question this is the content I get when I insert the correct password(`hey`) `b' \n400 Bad Request\n

    Bad Request

    \n

    The browser (or proxy) sent a request that this server could not understand.

    \n'`. Sorry for not putting this in the main question.
    – james kaly Jan 05 '17 at 13:39
  • @jameskaly: don't put this into the question, that is now solved. You have a new issue. That's an error message returned by Flask, look at the logs that Flask produces to learn more as to why it is going wrong. – Martijn Pieters Jan 05 '17 at 13:40
  • @jameskaly: if you can't solve it from that information, you should post a *new* question. Do include the error messages you found in the logs too. – Martijn Pieters Jan 05 '17 at 13:40
  • @jameskaly: answer updated, you missed some details in the [Requests documentation](http://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file). – Martijn Pieters Jan 05 '17 at 13:56