Python CGIHTTPServer устанавливает типы файлов для динамических и статических страниц
В этом вопросе ( Каталоги по умолчанию для Python CGIHTTPServer) подробно описано, как задать пути для расположения файлов cgi-bin для Python CGIHTTPServer. В результате тестирования кажется, что вы не можете смешивать файлы.py и.html в одной и той же папке: в cgi-bin он хорошо обрабатывает файлы.py, но попросил предоставить статический html-файл, который я получил
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
Это действительно предполагаемое поведение, или я что-то упустил? Разреженная и непрозрачная документация гласит: "Однако класс будет запускать сценарий CGI, а не служить им в качестве файла, если он предполагает, что он является сценарием CGI. Используются только CGI на основе каталогов - другая общая конфигурация сервера заключается в обрабатывать специальные расширения как обозначающие CGI-скрипты."
Как мне сделать "относиться к специальным расширениям как к обозначениям CGI-скриптов". Какой метод или настройку я использую, или какие волшебные слова я произношу? Или это просто неумело сформулированная подсказка, которую я просто не могу сделать?
Я использую это только для быстрых тестов, и хотя я могу реструктурировать в отдельные файлы.py и.html, у меня есть другие ограничения, которые делают это болезненным упражнением.
2 ответа
Я взял оригинал is_cgi()
от CGIHTTPServer.py
и добавить два элемента
CGIHTTPServer.
вCGIHTTPServer._url_collapse_path(self.path)
использовать его вне файлаCGIHTTPServer.py
и что более важно: проверка расширения
if not tail.endswith('.html'):
но это можно сделать лучше.
Я не пользовалась
if tail.endswith('.py'):
потому что сервер может выполнять скрипты на других языках, если вам нужно - т.е. Perl
, PHP
, Bash
, так далее.
Код:
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()
Вам необходимо определить, какой тип файла запрашивается (py/cgi или статический файл). Миметипы могут помочь. Когда запрашивается статический файл, вы можете вызвать другой скрипт cgi, который доставит ваш статический файл. Btw. Вы должны использовать wsgi вместо устаревшего cgi.
Я изменил какой-то старый код (py2.7), который я получил - это очень уродливо и я никогда не использовал его - но когда вы помещаете статический файл 'dev.html' в 'handler.cgi_directory', он должен обслуживаться 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()