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.
Related
I am trying to build a redirect service that will allow me to track clicks within emails I send to foreign websites.
Example of the URL of this script:
https://example.com/cgi-bin/redir.py?rurl=https%3A%2F%2Fwww.example.com%2Fde&utm_content=test
I am using Apache2 on Ubunut20.04 with the cgi module, calling the following redir.py script:
#!/usr/bin/python3
import webbrowser
redirect_url = "https://www.example.com"
webbrowser.open(redirect_url)
Now this results in the following error:
End of script output before headers: redir.py
Adding a header:
print('Content-Type: text/plain')
print('')
print('hello world')
With this "hello world" output I get exactly this, a "hello world" message.
How to redirect if a header is needed?
Everything you print gets returned to the requesting browser. Your python file should look like this:
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
print("Content-Type: text/html\n\n")
print()
print("<meta http-equiv=\"refresh\" content=\"0; url=TARGETURL\" />")
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.
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>
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/
My .py file executes ok in terminal, but gives this error in the browser
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
...
...
Here is the .py file:
#!/usr/bin/python
import cgi
import cgitb; cgitb.enable()
print "Content-Type: text/html\n\n" # HTML is following
print # blank line, end of headers
print "<TITLE>CGI script output</TITLE>"
print "<H1>This is my first CGI script</H1>"
print "Hello, world!"
Should i be saving this as a .cgi file? I have tried with the same errors, i have tried many files like this and none work, i am sure the apache server is working as there are other .cgi scripts running from the same directory without issues.
I have also tried:
#!/usr/local/bin/python &
#!/usr/bin/local/python
Any help appreciated.
EDIT
error log output:
(2) No such file or directory: exec of '.../.../.../test.py' failed
Premature end of script headers: test.py
Here is something I wrote up a while ago. These are some good things to look for when troubleshooting Python CGI.
There are some tips to getting Python working in CGI.
Apache setup: This may be old
Add python as a CGI by modifying the following in the configuration:
Options Indexes FollowSymLinks ExecCGI
AddHandler cgi-script .cgi .py
Always browse the pages through Apache.
Note that viewing files in the filesystem through a browser works for most things on an html page but will not work for CGI. For scripts to work they must be opened through the htdocs file system. The address line of your browser should look like:
\\127.0.0.1\index.html or
\\localhost\index.html
If you open a file up through the file system the CGI will not work. Such as if this is in the location bar of your browser:
c:\Apache\htdocs\index.html (or some other example location)
Convert end of lines of scripts to Unix format:
Most editors have options to "show end of lines" and then a tool to convert from Unix to PC format. You must have the end of lines set to Unix format.
State the path to the Python interpreter on the first line of the CGI script:
You must have one of the following lines as the first line of your Python CGI script:
#!C:\Python25\Python.exe
#!/usr/bin/python
The top line is used when you are debugging on a PC and the bottom is for a server such as 1and1. I leave the lines as shown and then edit them once they are up on the server by deleting the first line.
Print a content type specifying HTML before printing any other output:
This can be done simply by adding the following line somewhere very early in your script:
print "Content-Type: text/html\n\n"
Note that 2 end of lines are required.
Setup Python scripts to give debugging information:
Import the following to get detailed debugging information.
import cgitb; cgitb.enable()
An alternative if cgitb is not available is to do the following:
import sys
sys.stderr = sys.stdout
On the server the python script permissions must be set to execute.
After uploading your files be sure to edit the first line and set the permissions for the file to execute.
Check to see if you can hit the python script directly. If you can't, fix with the above steps (2-6). Then when the Python script is working, debug the shtml.