wordpress on apache2 running python as cgi - python

So here is what I want to do:
On my Raspi a python program is running. On a wordpress site the current state of the program should be displayed and some configurations should be changeable.
Here is the problem:
Whenever I want to execute the python script, I get a 500 error code. It doesn't matter if I just want to display the value or change it. I'm new to html, cgi and apache, tried a lot but now I have no clue how to continue. I'd appreciate it a lot if someone could point me in the right direction.
Here are my configurations:
Apache:
Edited the file /etc/apache2/apache2.conf:
<Directory /var/www/>
Options +ExecCGI +Indexes +FollowSymLinks
AddHandler cgi-script .cgi .py
AllowOverride None
Require all granted
</Directory>
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Require all granted
</Directory>
<Directory "/var/www/cgi-bin">
Options All
</Directory>
I also ran sudo a2enmod cgi
The webserver directory (/var/www/) looks like this:
.
├── cgi-bin
└── html
├── pma
│   └── ...
└── wordpress
└── ...
Wordpress:
On a wordpress site, I go into the "text" mode and have the following html code:
Curent Value: <form action="/cgi-bin/apfautostartval.py" method="get"></form>
<form action="/cgi-bin/apfcgi.py" method="post" target="_blank">
<input name="autoTest" type="radio" value="True" /> True (do automatic scan)
<input name="autoTest" type="radio" value="False" /> False (do manual scan)
<input type="submit" value="Submit" /></form>
Python files:
The apfautostartval.py should just get the value from the config.ini and post it:
#!/usr/bin/python3
import configparser
import os
import cgi, cgitb
cgitb.enable()
# Create config parser
config = configparser.ConfigParser()
configFilePath = os.path.join(os.path.sep,"home","pi",..., "config.ini")
config.read(configFilePath)
print("Content-type: text/html")
print()
print("<!DOCTYPE html>")
print("<html>")
print("<body>")
print(str(config['SETTINGS']["autoTest"]))
print("</body>")
print("</html>")
And finally the apfcgi.py should receive the submitted new value and write it to the config.ini:
#!/usr/bin/python3
import configparser
import os
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
cgitb.enable()
# Create config parser
config = configparser.ConfigParser()
configFilePath = os.path.join(os.path.sep,"home","pi",..., "config.ini")
print("Content-type: text/html")
print()
print("<!DOCTYPE html>")
print("<html>")
print("<body>")
# Receive autotest command from web site
if form.getvalue("autoTest"):
config.read(configFilePath)
if form.getvalue("autoTest").lower() == "true":
config['SETTINGS']["autoTest"] = "True"
else:
config['SETTINGS']["autoTest"] = "False"
with open(configFilePath, 'w') as configfile:
config.write(configfile)
print("</body>")
print("</html>")

I had the same problem. The problem was in the encoding. By default, ConfigParser.read() uses the encoding=none parameter. I specified utf-8 and it worked.
config = configparser.ConfigParser()
config.read(configFilePath, encoding='utf-8')

Ok I have found the solution for one part of the problem:
When changing the value make sure, you granted permissions to the file for cgi scripts:
in /etc/apache2/apache2.config add:
<Directory "/home/pi/dirToTheConfigFile/">
Options +ExecCGI +Indexes +FollowSymLinks
AddHandler cgi-script .cgi .py
AllowOverride None
Require all granted
</Directory>
And make sure, the user www-data is allowed to modify the file.
In general add cgitb.enable() to your python scripts, so for html 500 errors you will get a detailed error message in the /var/log/apache2/error.log file
For receiving data the following Solution was found:
The Python script was unfortunately owned by root and therefore cound not be executed. I changed the permissions.
The receiving html in the wordpress has been rewritten, too:
<iframe src="/cgi-bin/apfautostartval.py" width="100" height="29.5" frameborder="0" marginwidth="8" marginheight="0" scrolling="no" align="bottom"></iframe>
It's now an iframe and displays whatever is returned.

Related

Executing Python cgi files in Apache on Windows

I am trying to run a very simple "Hello World" program with Apache.
However, Apache returns a 500 Internal Server Error when it tries to execute my python file.
I've read several similar topics on here and tried the suggestions, no luck.
Things I have tried:
Including the AddHandler with .py files to the .conf file
Adding ExecCGI to the "Options Indexes" line in the .conf.
Making sure the first thing output is ""Content-Type:text/html" with 2 end of line characters.
Adding a shebang line to the top of the python file to direct to the Python interpreter. I'm not sure if I'm doing this part right.
Restarting Apache
The tools I am using include:
Windows 7
Python 3.5
Apache 2.4
My code:
The HTML File (in the htdocs folder in the Apache folder):
<form action="/cgi-bin/hello_get.py" method="post">
First Name: <input type="text" name="first_name"> <br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>
The python file (in the cgi-bin folder):
# Note that I tried this without the C:/ also
#!C:/Users/MyName/workspace/Flask/flask/Scripts
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
print("Content-Type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Hello - Second CGI Program</title>")
print("</head>")
print("<body>")
print("<h2>Hello %s %s</h2>" % (first_name, last_name))
print("</body>")
print("</html>")
I figured it out.
In my shebang line, instead of:
#!C:/Users/MyName/workspace/Flask/flask/Scripts
I should have:
#!C:/Users/MyName/workspace/Flask/flask/Scripts/python.exe
I thought my shebang should have a path to where the python interpreter lives, I didn't realize I needed the actual full path of the interpreter.
It is working now.
So to recap, if you are having this issue after following these instructions:
http://editrocket.com/articles/python_apache_windows.html
Make sure that if you are using Windows the path is the full absolute path from the C:/ drive to the python.exe executable.

malformed header from script index.py Bad header

I want to run python code in apache2(ubuntu 14.04) server. I have followed these steps and getting Error:
Step 1:
Configuration 1: I have created a directory and file under
/var/www/cgi-bin
Configuration 2 : I have edited /etc/apache2/sites-available/000-default.conf
Alias /cgi-bin /var/www/cgi-bin
<Directory "/var/www/cgi-bin">
Options Indexes FollowSymLinks ExecCGI
AddHandler cgi-script .cgi .py
Allow from all
</Directory>
<Directory /var/www/cgi-bin>
Options All
</Directory>
Step 2:
and my python script is: index.py
#!/usr/bin/env python
import cgi;
import cgitb;cgitb.enable()
print "Content-Type: text/plain\n"
print "<b>Hello python</b>"
step 3:
When i ran through chrome browser using:
URL : http://localhost/cgi-bin/index.py
step 4:
I am getting this Error in error-log
malformed header from script 'index.py': Bad header: Hello Python
You should end your header with \r\n, then you must print out yet another \r\n to signal that the body is coming.
(In other words, it's interpreting your body as a Header because the headers were never terminated)
Try this script
#!/usr/bin/env python
import cgi;
import cgitb;cgitb.enable()
print "Content-Type: text/html"
print "" #use this double quote print statement to add a blank line in the script
print "<b>Hello python</b>"
There should be one line space between header and main html content. That's why we have to use extra print statement before starting html tags in script.
I had this issue with the flush mechanism when you need to print a file.
This code responds to a http request if it is called via e.g. apache2.
import sys
print("Content-type: image/png", end="\r\n\r\n", flush=True)
sys.stdout.buffer.write(bytes(open("file.png","rb").read()))
end="\r\n\r\n" adds an empty line to begin the body
flush=True forces python to print the lines as intended. In my case, the header was printed wrong.

How to use AJAX to receive content from Python

I am trying to use AJAX to update a table with data returned from a Python script. When I request the Python script using AJAX, the returned text is the entire python script file, not just the content in the print commands.
My AJAX file:
...standard loadXMLDoc function with callback from W3C AJAX tutorial...
function doNow()
{
loadXMLDoc("cgi-bin/get.py",function()
{
if (request.readyState==4 && request.status==200)
{
document.getElementById("active_items").innerHTML=request.responseText;
}
});
}
window.onload=doNow();
For simplicity, I've used python files as simple as:
print("<div>something</div>")
or
import cgi
import cgitb
cgitb.enable(display=0, logdir="/path/to/logdir")
if __name__ == "__main__":
print("Content-type:text/html\n\n")
print("<div>something</div>")
When I load the page, the content of <div id="active_items"> is:
print("
something
")
I have already:
Set the get.py file to executable using chmod 755 get.py
Verified that CGI privileges are enabled on my server (i.e. other .cgi scripts work)
Verified that my AJAX script works with other static files, such as a .txt file
I'm sure I'm missing something obvious, but I would love some help!
Add to the top of your Python file (assumes *nix environment):
#!/usr/bin/env python
If you haven't already, ensure that your web server treats .py Python scripts as CGI scripts. An example for Apache is this directive:
<Directory /srv/www/yoursite/public_html>
Options +ExecCGI
AddHandler cgi-script .py
</Directory>

How do I deal with URL reroutes in Python Bottle and Apache .htaccess?

I am currently trying to create a simple standalone application using Python Bottle.
My entire project is under pytest/, where I have dispatch.fcgi and .htaccess.
dispatch.fcgi:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import bottle
import os
from bottle import route, run, view
#route('<foo:path>')
#view('index')
def pytest(foo = ''):
return dict(foo=foo)
APP_ROOT = os.path.abspath(os.path.dirname(__file__))
bottle.TEMPLATE_PATH.append(os.path.join(APP_ROOT, 'templates'))
app = bottle.default_app()
if __name__ == '__main__':
from flup.server.fcgi import WSGIServer
WSGIServer(app).run()
.htaccess:
DirectoryIndex dispatch.fcgi
The following URLs give me the corresponding values of foo:
url.com/pytest/
> /pytest/
url.com/pytest/dispatch.fcgi
> /pytest/dispatch.fcgi
url.com/pytest/dispatch.fcgi/
> /
url.com/pytest/dispatch.fcgi/foo/bar
> /foo/bar
url.com/pytest/dispatch.fcgi/pytest/
> /pytest/
How can I make the URLs uniform? Should I deal with the rerouting with the .htaccess file or within the Python code? What would be considered most pythonic, or best practices?
I am running Python 2.6.6, Bottle 0.11.6, Flup 1.0.2, and Apache 2.2.24. I would also like to point out that I'm using shared hosting, and mod_wsgi is out of the question (if that makes a difference).
EDIT
This is what I expect to see:
url.com/pytest/
> <redirect to url.com/pytest/dispatch.fcgi>
url.com/pytest/dispatch.fcgi
> <empty string>
url.com/pytest/dispatch.fcgi/
> /
url.com/pytest/dispatch.fcgi/foo/bar
> /foo/bar
url.com/pytest/dispatch.fcgi/pytest/
> /pytest/
If there is a more efficient way of tackling this problem, please let me know.
Couple of thoughts. Hopefully some or all of these will help.
1) You can do the redirect from '/' to '/pytest/dispatch.fcgi' like this:
#route('/')
def home():
bottle.redirect('/pytest/dispatch.fcgi')
2) Can you use ScriptAlias instead of DirectoryIndex? I see you're on a shared environment, so I'm not sure. My bottle/apache servers use ScriptAlias (or WSGIScriptAlias) and it works perfectly there; and it'd make more clear the way your code interacts with apache.
3) If worse came to worst, could you hackishly detect the case where foo == '/pytest/dispatch.fcgi' and act accordingly? (E.g., treat it as empty string.)
Hope this helps. Please keep us posted!
Bottle seems to be confused because it expects a trailing slash, followed by parameters. For that reason I changed my .htaccess file to read like this:
DirectoryIndex dispatch.fcgi/
Another option would be to have all errors fall back onto the dispatch script. That can be done with mod_rewrite:
<IfModule mod_rewrite.c>
Options -MultiViews
# rewrite for current folder
RewriteEngine On
RewriteBase /pytest
# redirect to front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ dispatch.fcgi/ [R=301,QSA,L]
</IfModule>
or FallbackResource:
FallbackResource /pytest/dispatch.fcgi/

CGI not executing python - 500 internal server error

I have a few python scripts that I'd like to execute and the following configuration:
Ubuntu 10.04, Apache2, Python 2.6, mod_python and mod_wsgi installed.
I've followed the instructions on the following sites:
http://bytes.com/topic/python/answers/474462-apache-python-ubuntu
http://apache.active-venture.com/cgi-configure.html
http://modpython.org/live/current/doc-html/inst-testing.html
http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide
http://wiki.apache.org/httpd/DistrosDefaultLayout
The default file in sites-available :
<VirtualHost *:80>
ServerAdmin webmaster#localhost
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AddHandler mod_python .py
AddHandler cgi-script .cgi py
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
I'm getting the 500 internal server error.
I've also changed the permissions of the files to 755
The py files simply prints some text that should appear on the page.
What should I do?
Thanks
[edit]: Update, it's related to bugs in the py file
error log shown below.
Traceback (most recent call last):
File "/usr/lib/cgi-bin/amissa2.py", line 80, in <module>
zoom_factor = int(parms.getfirst('zoom')) * int(parms.getfirst('zsize'))
TypeError: int() argument must be a string or a number, not 'NoneType'
It appears to be an error in converting from None to int, over here:
zoom_factor = int(parms.getfirst('zoom')) * int(parms.getfirst('zsize'))
Any hint on how this can such a conversion be done?
If parms.getfirst('zoom') or parms.getfirst('zsize') return None, you are probably not providing these in your URL (? dunno what these parms are, just guessing). Define the behaviour you want when these are missing (will it mean a "0" zoom, or since you are multiplying, "1" makes more sense?).
Then create your own conversion function that knows how to translate a None to int (depending on your defined behaviour) and call it instead of int().
def convert(value):
if value is None:
return 0 # or 1, or whatever
else:
return int(value)
You're not loading the wsgi module.
LoadModule wsgi_module modules/mod_wsgi.so
Also, you need only mod_wsgi OR mod_python installed. Not both unless you have a specific need to do so.

Categories