I am attempting to display an image on localhost. As a first step, I have created a sever script in python
#!/usr/bin/env python
import BaseHTTPServer
import CGIHTTPServer
import cgitb; cgitb.enable() ## This line enables CGI error reporting
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("", 8000)
handler.cgi_directories = ["/"]
httpd = server(server_address, handler)
httpd.serve_forever()
The image is placed within the same directory where this script is executing.
Subsequently http://localhost:8000/test.jpg is typed in the browser.
The browser fails to render the image with an error:
The image "http://localhost:8000/test.jpg" cannot be displayed because it contains errors.
The server script throws an error like
File "/usr/lib/python2.7/CGIHTTPServer.py", line 253, in run_cgi
os.execve(scriptfile, args, env)
OSError: [Errno 8] Exec format error
I have tried displaying text and the server works fine with lot of examples. Except that it fails to load images. Where am I going wrong?
The problem was solved. I moved the test.jpg into a sub-directory within the
server directory.
Your code is attempting to execute the test.jpg as a cgi script. If you remove the CGIHttpRequestHandler and instead use SimpleHTTPServer.SimpleHTTPRequestHandler you will get your image back. If you need both, then you need to put the image somewhere else.
CGI is used to execute server-side scripts, not to serve static content. It will therefore attempt to execute files that are being served (in this case, attempting to execute an image): os.execve(scriptfile, args, env).
Execution is equivalent to running the file at your shell.
Use SimpleHTTPServer for static content, such as images.
I believe the error is because you have no html page setup.
Your python script although is running a server on your localhost, but you need html/css pages
to actually display pictures and words.
Related
Environment:
Python 3.7.7
Windows 10 64bits
Problem:
I have my main script doing some stuff. I need to display a report of its activities.
I made a mini website which display the data activity.
I placed this mini website in a subfolder ‘/report’.
Inside this subfolder ‘/report’, I have the script Report.py which launch the http.server
My main script is executing this Report.py in order to open the mini website in a browser. Since 3 days I am working on it and I didn’t succeed to make it work.
So this is how my code is organized:
main.py
report/Report.py
report/index.py
here is main.py:
from report import Report
Report.StartReportTool()
and here is what I tried inside the Report.py file and which error I get. These codes below are the content of method "StartReportTool()":
N°1:
port=8888
address=("",port)
server=http.server.HTTPServer
handler=http.server.CGIHTTPRequestHandler
handler.cgi_directories=["report"]
httpd=server(address,handler)
print(f"Report tool server started on port {port}")
webbrowser.open(f'http://localhost:{port}/report/index.py', new=2)
httpd.serve_forever()
Error: The browser open url ‘http://localhost:8888/report/index.py’display the source code of index.py instead of executing the script index.py
================================
N°2 I edited the url pass to webbrowser.open
port=8888
address=("",port)
server=http.server.HTTPServer
handler=http.server.CGIHTTPRequestHandler
handler.cgi_directories=["report"]
httpd=server(address,handler)
print(f"Report tool server started on port {port}")
webbrowser.open(f'http://localhost:{port}/index.py', new=2) #<= I change this line
httpd.serve_forever()
Error: The browser opens this URL ‘http://localhost:8888/index.py’ and displays this error message:
Error response
Error code: 404
Message: File not found.
Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.
================================
N°3
I edited the folder pass to handler.cgi_directories
port=8888
address=("",port)
server=http.server.HTTPServer
handler=http.server.CGIHTTPRequestHandler
handler.cgi_directories=["/"] #<= I change this line
httpd=server(address,handler)
print(f"Report tool server started on port {port}")
webbrowser.open(f'http://localhost:{port}/index.py', new=2)
httpd.serve_forever()
Error: The browser opens this URL ‘http://localhost:8888/index.py’ and shows this error message in the browser:
Error response
Error code: 404
Message: No such CGI script ('//index.py').
Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.
I don’t know what else to try. Does anyone have any idea what am I doing wrong?
This worked for me (notice the slash):
handler.cgi_directories=["/report"]
I am developing a python script that opens a file, gets the data inside this file and send it via url to a Django server.
import os
import urllib
stockPath = "/Desktop/myfile.txt"
f = open(stockPath)
mydata = f.readline()
print (mydata)
params = urllib.urlencode({'mydata': mydata})
f = urllib.urlopen("http://127.0.0.1:8000/home/%s" % params)
print (f.geturl())
This is working perfect in local. Now for some reason I have to start the Django server in another machine.
Of course I install python and django in that new machine and I start Django server. So everything is running ok.
This new machine is in the same network as mine, so I can reach it, the ping works.
The problem is that if I change the ip address for the new one, it doesn't work:
f = urllib.urlopen("http://10.32.2.94:8000/home/%s" % params)
I would be gratefull if sombebody could help me.
You need to listen on all interfaces, for example:
./manage.py runserver 0.0.0.0:8000
By default it only listens locally.
I have just made a server (only for localhost) in Python to execute by CGI to execute and try my Python scripts. This is the code of the file that executes the server:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import BaseHTTPServer
import CGIHTTPServer
import cgitb
cgitb.enable() ## This line enables CGI error reporting
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("", 8000)
handler.cgi_directories = ["/"]
httpd = server(server_address, handler)
httpd.serve_forever()
When I access some script in the server (http://127.0.0.1:8000/index.py) there is no problem, but when I access the server (http://127.0.0.1:8000/) it shows:
Error response
Error code 403.
Message: CGI script is not executable ('//').
Error code explanation: 403 = Request forbidden -- authorization will not help.
It's like if index files aren't set as default file to access when access a folder instead of a specific file...
I would like to be able to access to http://127.0.0.1/index.py when I access http://127.0.0.1/. Thanks for everything.
Python's built-in HTTP server is extremely basic, so it doesn't include such feature. However you can implement it yourself by subclassing CGIHTTPRequestHandler, probably replacing the is_cgi function.
If you use handler.cgi_directories = ["/cgi"], you can place an index.html file in "/". And of course, if you want a cgi script index.py as default, you can use the index.html for forwarding...
I did try to modify is_cgi function and it's working!
def is_cgi(self):
collapsed_path = _url_collapse_path(self.path)
if collapsed_path == '//':
self.path = '/index.py'
collapsed_path = _url_collapse_path(self.path)
dir_sep = collapsed_path.find('/', 1)
head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep + 1:]
if head in self.cgi_directories:
self.cgi_info = head, tail
return True
return False
I put this method into this following class:
class CGIHandlerOverloadIndex(CGIHTTPServer.CGIHTTPRequestHandler):
I've got the following minimal code for a CGI-handling HTTP server, derived from several examples on the inner-tubes:
#!/usr/bin/env python
import BaseHTTPServer
import CGIHTTPServer
import cgitb;
cgitb.enable() # Error reporting
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("", 8000)
handler.cgi_directories = [""]
httpd = server(server_address, handler)
httpd.serve_forever()
Yet, when I execute the script and try to run a test script in the same directory via CGI using http://localhost:8000/test.py, I see the text of the script rather than the results of the execution.
Permissions are all set correctly, and the test script itself is not the problem (as I can run it fine using python -m CGIHTTPServer, when the script resides in cgi-bin). I suspect the problem has something to do with the default CGI directories.
How can I get the script to execute?
My suspicions were correct. The examples from which this code is derived showed the wrong way to set the default directory to be the same directory in which the server script resides. To set the default directory in this way, use:
handler.cgi_directories = ["/"]
Caution: This opens up potentially huge security holes if you're not behind any kind of a firewall. This is only an instructive example. Use only with extreme care.
The solution doesn't seem to work (at least for me) if the .cgi_directories requires multiple layers of subdirectories ( ['/db/cgi-bin'] for instance). Subclassing the server and changing the is_cgi def seemed to work. Here's what I added/substituted in your script:
from CGIHTTPServer import _url_collapse_path
class MyCGIHTTPServer(CGIHTTPServer.CGIHTTPRequestHandler):
def is_cgi(self):
collapsed_path = _url_collapse_path(self.path)
for path in self.cgi_directories:
if path in collapsed_path:
dir_sep_index = collapsed_path.rfind(path) + len(path)
head, tail = collapsed_path[:dir_sep_index], collapsed_path[dir_sep_index + 1:]
self.cgi_info = head, tail
return True
return False
server = BaseHTTPServer.HTTPServer
handler = MyCGIHTTPServer
Here is how you would make every .py file on the server a cgi file (you probably don't want that for production/a public server ;):
import BaseHTTPServer
import CGIHTTPServer
import cgitb; cgitb.enable()
server = BaseHTTPServer.HTTPServer
# Treat everything as a cgi file, i.e.
# `handler.cgi_directories = ["*"]` but that is not defined, so we need
class Handler(CGIHTTPServer.CGIHTTPRequestHandler):
def is_cgi(self):
self.cgi_info = '', self.path[1:]
return True
httpd = server(("", 9006), Handler)
httpd.serve_forever()
Summary: Python cgi script runs as expected when called from a simple python debug server, but fails with 500 Premature end of script headers error when run from ~/public_html/cgi-bin/
Problems
My CGI script works fine when run through a simple python webserver, and I see the right output when navigating to nameofmyhost.com:8080/...
However, when running the same script from my public_html/cgi-bin directory it gives me a 500 premature end of script headers error. What can I do to fix this?
The permissions on the file seem ok:
drwxrwxrwx cgi-bin
-rwxr-xr-x cgi-bin/generate_list.py
This is simple_httpd.py, the simple python webserver
from http.server import HTTPServer, CGIHTTPRequestHandler
port = 8080
httpd = HTTPServer(('', port), CGIHTTPRequestHandler)
print("Starting simple_httpd on port: " + str(httpd.server_port))
httpd.serve_forever()
CGI script generate_list.py:
#! /usr/local/bin/python3
import athletemodel
import yate
import glob
data_files = glob.glob("data/*.txt")
athletes = athletemodel.put_to_store(data_files)
print(yate.start_response())
print(yate.include_header("Coach Kelly's List of Athletes"))
print(yate.start_form("generate_timing_data.py"))
print(yate.para("Select an athlete from the list to work with:"))
for each_athlete in athletes:
print(yate.radio_button("which_athlete", athletes[each_athlete].name))
print (yate.end_form("Select"))
print(yate.include_footer({"Home": "/index.html"}))
I'm guessing I need to maybe explicitly state my directory somewhere, maybe?
PS: I am going through the Head First Python book by Oreilly
Debugging steps
Check that the server can locate my files
Server finds simple html file in public_home [OK]
Check that the CGI script can execute without error.
Content-type: text/html
<html>
<head>
<title>Coach Kelly's List of Athletes</title>
[...]
CGI script ran from command line - outputs as expected [OK]
Check that the server can execute a simple CGI script in the same location
Try a simple CGI script to see if the server is able to execute any CGI scripts at all:
#!/usr/local/bin/python3
print("Content-Type; text/html")
print("")
print("<html><body><h1>hello</h1></body></html>")
Server fails to execute simple CGI script, giving the same error [FAIL]
Fixes
Fix 1: Change the data path to be absolute instead of relative:
- data_files = glob.glob("data/*.txt")
+ data_files = glob.glob("/home/delliott/public_html/webapp/data/*.txt")
The problem is that the base of your school webserver is not the same as the base of the simple_httpd.py server. This means that you will have to provide absolute paths to your data directory instead of relative paths.
Change the following lines:
- data_files = glob.glob("data/*.txt")
+ data_files = glob.glob("/home/<username>/public_html/data/*.txt")
This should now behave as expected (if I understand your problem correctly.)
[Edit]: A quick way to check if your cgi-bin scripts work is to run them from the command line. Log into your school server and try the cgi script ion its own:
$ cd /home/<username>/public_html/
$ python3 my_cgi_script.py
This should print out the html that you expect, or a stack trace.