Executing Python cgi files in Apache on Windows - python

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.

Related

Does Python CGIHTTPServer decode plus sign(+) in URL into blank space?

In my html, I have below form:
<form method=GET action="/cgi-bin/encry.sh">
<table nowrap>
<tr>
<td>Plain Text:</TD>
<TD><input type="text" name="PlainText"></td>
</tr>
</table>
<input type="submit" value="Encrypt">
</form>
After inputing "aaa +=" and clicking the button,
in my cgi-bin/encry.sh, the QUERY_STRING is assigned as "aaa++=" rather than "aaa +=", nor "a+%2B%3D".
Is that correct behavior, and if so how can I get the blank space correctly?
If not, is that fixed in any later CGIHTTPServer version?
Below provides some info about CGIHTTPServer.py in my CentOS 7.2:
HiAccount-4# md5sum /usr/lib64/python2.7/CGIHTTPServer.py
564afe4defc63001f236b0b2ef899b58 /usr/lib64/python2.7/CGIHTTPServer.py
HiAccount-4# grep __version /usr/lib64/python2.7/CGIHTTPServer.py -i
__version__ = "0.4"
HiAccount-4# grep unquote /usr/lib64/python2.7/CGIHTTPServer.py -i -C 3 -n
84- path begins with one of the strings in self.cgi_directories
85- (and the next character is a '/' or the end of the string).
86- """
87: collapsed_path = _url_collapse_path(urllib.unquote(self.path))
88- dir_sep = collapsed_path.find('/', 1)
89- head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
90- if head in self.cgi_directories:
--
164- env['SERVER_PROTOCOL'] = self.protocol_version
165- env['SERVER_PORT'] = str(self.server.server_port)
166- env['REQUEST_METHOD'] = self.command
167: uqrest = urllib.unquote(rest)
168- env['PATH_INFO'] = uqrest
169- env['PATH_TRANSLATED'] = self.translate_path(uqrest)
170- env['SCRIPT_NAME'] = scriptname
Thanks in advance!
After trying the CGIHTTPServer from python2.7.18, I think the asked question is a known issue in 2.7.5, which was my version, and not sure which version fixed it.
The problem is in:
/usr/lib64/python2.7/CGIHTTPServer.py:
87: collapsed_path = _url_collapse_path(urllib.unquote(self.path))
In 2.7.18, the QUERY_STRING isn't decoded by CGIHTTPServer, and I need to decode it in my CGI script, but that's OK as it's "correct" encoded QUERY_STRING.
BTW, I didn't upgrade my python in OS from 2.7.5 to 2.7.18, but just extract CGIHTTPServer from python 2.7.18 source code and use it as:
nohup python ./CGIHTTPServer.py 7070 &
rather than
nohup python -m CGIHTTPServer 7070 &

problem executing a python cgi script in apache webserver

I have searched and read other posts with similar problems. I fixed the shebang line in the .py file and made sure that httpd.conf has correct config. Unfortunately, nothing has resolved my problem and I still get the dreaded errors -
[Mon Jun 01 10:37:02.994516 2020] [cgi:error] [pid 19596:tid 1196] (OS 1920)The file cannot be accessed by the system. : [client ::1:50159] couldn't create child process: 721920: upload_file.py
[Mon Jun 01 10:37:02.994516 2020] [cgi:error] [pid 19596:tid 1196] (OS 1920)The file cannot be accessed by the system. : [client ::1:50159] AH01223: couldn't spawn child process: C:/Users/raj_d/webroot/tsp_quick/cgi-bin/upload_file.py
The Python script -
#!"C:\Users\raj_d\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\python.exe"
import cgi, os
import cgitb
cgitb.enable()
form = cgi.FieldStorage()
# Get filename here.
fileitem = form['filename']
# Test if the file was uploaded
if fileitem.filename:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
else:
message = 'No file was uploaded'
print """\
Content-Type: text/html\n
<html>
<body>
<p>%s</p>
</body>
</html>
""" % (message,)
I have played with adding and removing quotes on the full path in the shebang and that hasn't helped.
I have these in httpd.conf -
LoadModule cgi_module modules/mod_cgi.so
<Directory "C:\Users\raj_d\webroot\tsp_quick\cgi-bin">
AllowOverride None
# Options None
Options +ExecCGI
AddHandler cgi-script .py
Require all granted
</Directory>
I made sure that python was excutable from the shebang path -
C:\>C:\Users\raj_d\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\python.exe
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
Any help will be appreciated.
Thanks in advance.
RD
Well, I figured it out.
First and foremost, one should always follow the guidelines :)
In my case, I gave up too quickly in running the script from command line. I had installed Python 3.8.3 from the Microsoft store and for some reason every time I ran the script from the command line, a new cmd window would popup and close very quickly. I was unable to change that behavior and couldn't see what was going wrong.
So I uninstalled python, downloaded the new installer from python's site, and installed in a common location where my dev tools are installed. Now, I could run my script from command line and was able to see what the actual problem was.
It turned out to be print! Here is the modified code which works just fine and the shebang became simpler as well.
#!C:\tools\python\\python.exe
import cgi, os
import cgitb
import time
cgitb.enable()
form = cgi.FieldStorage()
# Get filename here.
fileitem = form['filename']
# Test if the file was uploaded
if fileitem.filename:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.filename)
# open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
else:
message = 'No file was uploaded'
a = """Content-Type: text/html\n
<html>
<body>
<p>{}</p>
</body>
</html>
"""
print (a.format(message))
I had similar issues trying to execute *.py files in Apache on Windows. I followed the Apache CGI setup guide, but the problem (as you allude to) is with the Python executable in
C:/Users/../AppData/Local/Microsoft/WindowsApps/Python/
For some reason that I can't figure out, Apache won't allow you to use the Python interpreter in this location. I did as you suggested and uninstalled Python 3.10.x and re-installed on my D: drive and hey presto, it just worked.
I suspect this is a windows-only quirk, probably a security issue.

Python CGI to invoke another CGI script that runs a sensor in Raspberry

I have a python CGI program (says: scrip1), that I am using to set values for some variable for another python CGI script (says: script 2) using web browser. I am using the script 2 to run a Lidar Sensor. The problem is I can set the variable in script 2 using script 1. But script 2 is not executing after receiving variable. Script 2 suppose to start my sensor. Any possible solutions. (I would like to stick on CGI scripts)
#script 1
#!/usr/bin/python
import os
import cgi
import cgitb
print("Content-Type: text/html\r\n")
print("")
print'''<html>
<head><title>Form to enter sleep time</title></head>
<body>
<form action="/cgi-bin/test.py" method="post">
<html><label> enter sleep time</label>
<input type="number" name="sleeptime"/>
<input type="submit" name ="Submit" "></form>
</body>
</html>'''
#### second script is######
#!/usr/bin/python
import os
import cgi
import cgitb
import smbus
import time
print("Content-Type: text/html\r\n")
form = cgi.FieldStorage()
sleeptime = form.getfirst("sleeptime") #getting value from script 1 (form data)
#script to run the Lidar is as follows#
bus=smbus.SMBus(1)
addr=0x62
while True:
bus.write_byte_data(0x62,0x00, 0x04)
val_high=bus.read_byte_data(0x62,0x0f)
val_low=bus.read_byte_data(0x62,0x10)
dist_cm=val_high*256+val_low
print (dist_cm , " cm ")
time.sleep(sleeptime)
The extension of the first file is .py as well? Have you tried using .cgi extension (with contents remaining the same)

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>

Internal Server Error 500 - Python, CGI

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.

Categories