Reputation: 690
This question (Python CGIHTTPServer Default Directories) details how to set paths for location of cgi-bin files for Python CGIHTTPServer. From testing this, it seems that you cannot mix .py and .html files in the same folder: in cgi-bin it processes .py files fine, but asked to serve a static html file I get
127.0.0.1 - - [08/Jan/2017 10:51:22] "GET /dev.html HTTP/1.1" 200 -
Traceback (most recent call last):
File "/usr/lib/python2.7/CGIHTTPServer.py", line 248, in run_cgi
os.execve(scriptfile, args, env)
OSError: [Errno 8] Exec format error
127.0.0.1 - - [08/Jan/2017 10:51:22] CGI script exit status 0x7f00
Is this the real intended behaviour, or am I missing something? The sparse and opaque documentation says "The class will however, run the CGI script, instead of serving it as a file, if it guesses it to be a CGI script. Only directory-based CGI are used — the other common server configuration is to treat special extensions as denoting CGI scripts."
How do I do "treat special extensions as denoting CGI scripts". What method or setting do I use, or which magic words do I utter? Or is this just an ineptly worded tip-off that I just can't do it?
I'm only using this for quick tests, and while I could restructure to separate .py and .html files I have other constraints that would make this a painful exercise.
Upvotes: 1
Views: 939
Reputation: 142834
I took oryginal is_cgi()
from CGIHTTPServer.py
and add two elements
CGIHTTPServer.
in CGIHTTPServer._url_collapse_path(self.path)
to use it outside file CGIHTTPServer.py
and more important: checking extension
if not tail.endswith('.html'):
but it could be done better.
I didn't use
if tail.endswith('.py'):
because server may execute scripts in other languages if you need - ie. Perl
, PHP
, Bash
, etc.
Code:
import BaseHTTPServer
import CGIHTTPServer
class MyHandler(CGIHTTPServer.CGIHTTPRequestHandler):
# code from oryginal CGIHTTPServer.py
def is_cgi(self):
# v added `CGIHTTPServer.`
collapsed_path = CGIHTTPServer._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:
if not tail.endswith('.html'): # <-- new line
#if tail.endswith('.py'): # <-- new line
self.cgi_info = head, tail
return True
return False
# --- test ---
MyHandler.cgi_directories = ['/']
server = BaseHTTPServer.HTTPServer(('', 8000), MyHandler)
server.serve_forever()
Upvotes: 3
Reputation: 18126
You need to detect, what kind of file type is requested (py/cgi or a static file). Mimetypes may help. When a static file is requested, you could call another cgi script that delivers your static file. Btw. you should use wsgi instead of outdated cgi.
I modified some old code (py2.7) i got - that's very ugly and i never used it - but when you put a static file 'dev.html' in the 'handler.cgi_directory' it should be served by static.py.
server.py:
#!/usr/bin/python2
import BaseHTTPServer
import CGIHTTPServer
from mimetypes import MimeTypes
import urllib
class handler(CGIHTTPServer.CGIHTTPRequestHandler):
def is_cgi(self):
mime = MimeTypes()
request = self.path.split('?')
if len(request) == 2:
path, args = request
else:
path, args = request, None
if isinstance(path, list):
path = path[0]
url = urllib.pathname2url(path)
mime_type = mime.guess_type(url)
if 'python' in mime_type[0]:
self.cgi_info = '', self.path[1:]
return True
else:
self.cgi_info = '', '/static.py?path=%s' % path[1:]
print self.cgi_info
return True
server = BaseHTTPServer.HTTPServer
server_address = ("", 8000)
handler.cgi_directories = ["/somedir/..."]
httpd = server(server_address, handler)
httpd.serve_forever()
static.py:
#!/usr/bin/python2
import cgi
import urllib
from mimetypes import MimeTypes
form = cgi.FieldStorage()
mime = MimeTypes()
path = form.getvalue('path')
url = urllib.pathname2url(path)
mime_type = mime.guess_type(url)
print """Content-type: %s""" % mime
print
print open(path, 'r').read()
Upvotes: 2