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()
Другие вопросы по тегам