FieldStorage is empty despite a GET request with fields - python

I am beginning with python CGI programming, using mod_python in apache2, and am trying to retrieve the GET fields in HTTP requests to a simple .py page.
The code:
#!/usr/bin/python
import cgi
import cgitb; cgitb.enable()
print 'Content-type: text/html\n'
print '''
<html>
<body>
'''
form = cgi.FieldStorage()
l = len(form.keys())
print "<p>%s field(s) set.</p>" % l
print '''
</body>
</html>
'''
The page prints "0 field(s) set." What could be wrong here? So far in my search for an answer I haven't find a parameter in mod_python of apache2 that would block the transmission of GET fields to the CGI script.

cgi.FieldStorage relies on a multipart form being POSTed, not sent via GET. Change the method on your form and make sure you have multipart in the form tags:
<form action="" method="post" multipart>
<input type="file" name="file">
<input type="submit" name="submit" value="Submit">
</form>
When you use the GET method, cgi.FieldStorage just grabs the query string, which will at best give you the name of the file you're trying to submit.

Related

How to run python function once user inputs into form field

I am an html page with a form to enter your email:
<!DOCTYPE html>
<html>
<body>
<h1>The form novalidate attribute</h1>
<p>The novalidate attribute specifies that the form data should not be validated when submitted.</p>
<form action="/action_page.php" novalidate>
<label for="email">Enter your email:</label>
<input type="email" id="email" name="email" required><br><br>
<input type="submit" value="Submit">
</form>
<p><strong>Note:</strong> The novalidate attribute of the form tag is not supported in Safari 10 (or earlier).</p>
</body>
</html>
Is there a way to run a python script when the user enters his email address and then takes the input and runs it through this def function:
def send_email():
email_address=form_input
print(email_address)
So basically, when a user enters an email in the form, it takes the value and runs it through the send email function. I am new to using python with html so the syntax is confusing me. Any ideas or suggestions as to how to but it in the html file?
No, it is not possible to do it just in html.
If you use .php as backend script, read this php form handling
If you want to use python as backend script, you need to use ajax, e.g. ajax intro. In this case, need to run web server that take ajax request and respond the request

Pass HTML input to python script

I have a Python script and I want to create a very simple HTML form with 3 fields (username, password and an ID) and a submit button.
When I click Submit I just want to pass these three parameters into my Python script and run the script.
I tried to do it using CGI. I created a cgi-bin folder and added my test.py file in there. The Python code is the following:
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
username = form.getvalue('username')
password = form.getvalue('password')
room_id = form.getvalue('room_id')
#More code here...
Then I created an index.html file:
<!DOCTYPE html>
<html>
<body>
<form name="search" action="/[path to file]/test.py" method="get">
Username: <input type="text" name="username"> <br>
Password: <input type="password" name="password"> <br>
Room ID: <input type="text" name="room_id"> <br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Finally, I added a server.py file:
import CGIHTTPServer
CGIHTTPServer.test()
I run the server.py file and go to 0.0.0.0:8000. I gave the input but when I click Submit the python code is printed in the form and it is not executed.
I am looking for the simplest and fastest way to make this HTML form execute the script. It is only for test purposes and I do not want to spend time creating a complex web application.
Is CGI a good idea? If yes, what am I doing wrong?

tornado.web.stream_request_body: _xsrf missing error even with _xsrf input within html

Utilizing the Tornado library within Python I have come across a very unusual error. It seems that when I have decorated my file upload handler with '#tornado.web.stream_request_body' the webserver throws the error:
WARNING:tornado.general:403 POST /upload (ip-address): '_xsrf' argument missing from POST
WARNING:tornado.access:403 POST /upload (ip-address) 1.44ms
The code governing the upload is as follows:
#tornado.web.stream_request_body
class Upload(BaseHandler):
def prepare(self):
print self.request.headers
def data_received(self,chunk):
print chunk
#tornado.web.authenticated
def post(self):
self.redirect("/")
where my BaseHandler is a web.RequestHandler subclass with various helper functions (retrieving user info from cookies and whatnot).
Within my HTML template, I have the appropriate xsrf function call as seen here:
<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
{% raw xsrf_form_html() %}
<input type="file" name="upFile" required/>
<button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>
and is generating the proper xsrf input within the browser:
<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
<input type="hidden" name="_xsrf" value="2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367"/>
<input type="file" name="upFile" required/>
<button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>
When I turn off xsrf_cookies within the webserver settings, all is well and everything functions as normal. However I feel that this is not ideal.
While xsrf_cookies is set to False, if given a text file called "stuff.txt" with a body of "testfile" the output is:
------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="_xsrf"
2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367
------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="upFile"; filename="stuff.txt"
Content-Type: text/plain
testfile
------WebKitFormBoundary4iHkIqUNgfqVErRB--
From that output, my guess is that the xsrf value is being captured by the stream_request_body and not passed to the appropriate xsrf validation class.
Any help on this would be greatly appreciated. Thank you in advance!
Tornado does not currently (as of version 4.1) support streaming multi-part uploads. This means that uploads you wish to stream must be simple PUTs, instead of a POST that mixes the uploaded data with other form fields like _xsrf. To use XSRF protection in this scenario you must pass the XSRF token via an HTTP header (X-Xsrf-Token) instead of via a form field. Unfortunately this is incompatible with non-javascript web form uploads; you must have a client capable of setting arbitrary HTTP headers.

Displaying results from search API

I'm trying to get to grips with web2py/python. I want to get the user to fill in a search form, the term they search for is sent to my python script which should send the query to the blekko API and output the results to them in a new HTML page. I've implemented the following code but instead of my normal index page appearing, I'm getting the html response directly from blekko with '%(query)' /html appearing in it's search bar. Really need some help with this!
HTML form on the default/index.html page
<body>
<div id="MainArea">
<p align="center">MY SEARCH ENGINE</p>
<form name="form1" method="get" action="">
<label for="SearchBar"></label>
<div align="center">
<input name="SearchBar" type="text" id="SearchBar" value="" size = "100px"><br />
<input name="submit" type="submit" value="Search">
</div>
</form>
<p align="center"> </p>
Python code on the default.py controller
import urllib2
def index():
import urllib2
address = "http://www.blekko.com/?q='%(query)'+/html&auth=<mykey>"
query = request.vars.query
response = urllib2.urlopen(address)
html=response.read()
return html
I think you are misunderstanding how string formatting works. You need to put the address and query together still:
address = "http://www.blekko.com/?q='%(query)s'+/html&auth=<mykey>" % dict(query=request.vars.query)
Add a hidden field to your form, call it "submitted". Then reformat your controller function as such:
import urllib2
def index():
if request.vars.submitted:
address = "http://www.blekko.com/?q='%(query)'+/html&auth=<mykey>"
query = request.vars.query
response = urllib2.urlopen(address)
html=response.read()
return html
else:
return dict()
This will show your index page unless the form was submitted and the page received the "submitted" form variable.
The /html doesn't do anything. Glad your question got answered. There is python client code for the blekko search api here: https://github.com/sampsyo/python-blekko

Upload files without FieldStorage

How could i upload a file to a server without using FieldStorage in python?
Here is a toy program snippet that should help get you started. Try reading RFC 1867 as well for more guidance.
#!/usr/bin/python
import os
import sys
buf = sys.stdin.read(512)
print "Content-type: text/html\n\n";
print '<html>'
print '''
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="f">
<input type="submit">
</form>
'''
print buf
print '</html>'
You can use os.environ.items() to get a list of environment variables, notably CONTENT_LENGTH and CONTENT_TYPE (specifically the boundary key/pair) so you know where the demarcation points are for the uploaded content.

Categories