BMI-219 – Scientific Software Development
In the above example,
$ cd /home/socr/b/bmi219/current/z/conrad/cgi-bin $ ls -l total 4 -rw-rw-r-- 1 conrad bmi219 179 Apr 17 09:58 example.cgi $ chmod +x example.cgi $ ls -l total 4 -rwxrwxr-x 1 conrad bmi219 179 Apr 17 09:58 example.cgi $ ./example.cgi ???
-rw-rw-r--indicates that the file is not executable. The
chmodcommand adds execute permission for everyone.
The HTTP return code appears immediately after the HTTP request.
$ cd /usr/local/www/logs/plato-test-httpd/bmi219 $ grep example.cgi bmi219-ssl-access_log 188.8.131.52 - - [17/Apr/2017:09:56:19 -0700] "GET /z/conrad/cgi-bin/example.cgi HTTP/1.1" 401 362 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" 0/29321 184.108.40.206 - conrad [17/Apr/2017:09:56:22 -0700] "GET /z/conrad/cgi-bin/example.cgi HTTP/1.1" 500 613 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" 0/117099 220.127.116.11 - conrad [17/Apr/2017:09:56:46 -0700] "GET /z/conrad/cgi-bin/example.cgi HTTP/1.1" 200 50 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" 0/155331
401is "Unauthorized", and is normal when web site requires login.
200is "Success", so your script is being called
500is "Internal Server Error", so your script is being called but is generating output that Apache is treating as unacceptable HTTP response.
Your script should run to completion. It may complain about bad or missing input, but it should not generate syntax errors.
$ cd /home/socr/b/bmi219/current/z/conrad/cgi-bin $ ./example.cgi ???
If your script is throwing an exception, the (badly formatted) traceback will appear in the error log.
$ cd /usr/local/www/logs/plato-test-httpd/bmi219 $ grep example.cgi bmi219-ssl-error_log [Mon Apr 17 09:56:22.793106 2017] [cgi:error] [pid 34932] [client 18.104.22.168:39853] End of script output before headers: example.cgi [Mon Apr 17 09:58:34.034631 2017] [cgi:error] [pid 34932] [client 22.214.171.124:40281] AH01215: File "/home/socr/b/bmi219/current/z/conrad/cgi-bin/example.cg ", line 7, in
[Mon Apr 17 10:25:06.924289 2017] [cgi:error] [pid 55993] [client 126.96.36.199:40643] malformed header from script 'example.cgi': Bad header: [Mon Apr 17 10:25:06.925424 2017] [cgi:error] [pid 55993] [client 188.8.131.52:40643] AH01215: File "/home/socr/b/bmi219/current/z/conrad/cgi-bin/example.cg ", line 7, in
cgitbmodule catches errors for you and tries to generate nicely formatted HTML output from the traceback. The problem is that if your script generated HTTP headers (e.g.,
Content-Type: text/xml) first and then throws an exception, the output from
cgitbis treated as your type instead of HTML. To avoid this problem, you should buffer output from your script as a string, and only send the string if the script completes successfully.
#!/usr/bin/python2 # Enable CGI traceback generations. Turn off for production import cgitb; cgitb.enable() # Save standard output and replace it with a string buffer. # All script output will be appended to the string buffer. import sys, StringIO orig_stdout = sys.stdout sys.stdout = StringIO.StringIO() print "Content-Type: text/xml" print print "
" print "" # Script must have completed successfully so send # script output to the saved standard output. orig_stdout.write(sys.stdout.getvalue()) " # If an exception occurs in the script, script output # will not be sent back. Instead, cgitb will generate # HTML version of the traceback. raise ValueError("bad value") print "This is content" print "" print "
cgi-bindirectory next to the CGI scripts. If you are installing using
pip, use the
-toption to specify where the package should be installed. For example, to install the
social-authpackage in my
Note that you need to repeat this for each team member as well as the team production site since the installed package is only available to the script in the same directory.
$ pip install -t /home/socr/b/bmi219/current/z/conrad/cgi-bin social-auth
sqlite3wants write permission to the directory containing the database file when inserting or updating rows. Even if the database file itself is writable, your code can still get the dreaded
sqlite3.OperationalError: unable to open database fileerror if the directory is not writable.
This is a particularly subtle error if your script works when run on the server but fails when accessed from a web page because the same script is being run by two different users: user who logged in to the server and user apache.
$ ls -la total 16 dr-xr-xr-x 2 conrad ferrin 3864 Apr 19 15:40 ./ drwxrwxr-x 6 conrad ferrin 3864 Apr 19 15:39 ../ -rw-r--r-- 1 conrad ferrin 2048 Apr 19 15:29 t.db -rw-rw-r-- 1 conrad ferrin 237 Apr 19 15:31 t.py $ cat t.py import sqlite3 db = sqlite3.connect("t.db") c = db.cursor() #c.execute("create table t1 ( 'name' char(16) )"); c.execute("insert into t1 values ('conrad')") db.commit() for row in c.execute("select * from t1"): print row db.close() $ python t.py Traceback (most recent call last): File "t.py", line 6, in
c.execute("insert into t1 values ('conrad')") sqlite3.OperationalError: unable to open database file
datadirectory that is owned by user apache but writable by group bmi219. If your databases are created in there and made generally writable, then apache should be able to update your database.
$ ls -la data total 16 drwxrwxr-x 2 apache bmi219 3864 Apr 19 15:52 ./ drwxrwsr-x 6 conrad bmi219 3864 Apr 19 15:49 ../ -rw-rw-r-- 1 conrad ferrin 2048 Apr 19 15:52 t.db -rw-rw-r-- 1 conrad ferrin 237 Apr 19 15:50 t.py $ chmod go+w data/t.db $ ls -la data total 16 drwxrwxr-x 2 apache bmi219 3864 Apr 19 15:52 ./ drwxrwsr-x 6 conrad bmi219 3864 Apr 19 15:49 ../ -rw-rw-rw- 1 conrad ferrin 2048 Apr 19 15:52 t.db -rw-rw-r-- 1 conrad ferrin 237 Apr 19 15:50 t.py
onclickevent handler to initiate an AJAX request. If the
typeattribute for an HTML button is not specified, it defaults to submit. If the
onclickhandler returns false, then the form is not submitted. If it returns true, then the form is submitted and the entire web page is replaced by the response to the form submsstion; any AJAX request initiated by the replaced page is silently discarded.
returnthe value from whatever function is being called, or always
return falseafter calling the function.
onchangeevent handler for a