1. Dan Boitnott
  2. prise

Source

prise / src / web.py

import os.path
import BaseHTTPServer
import mimetypes
import shutil
import urlparse
import traceback
import socket

import pystache

RESOURCES = "resources"
STATIC = "static"
TEMPLATES = "templates"

def resourcePath(*args):
	return os.path.abspath(os.path.join(os.path.dirname(__file__), RESOURCES, *args))

def openResource(type, filename):
    dirPath = resourcePath(type)
    filePath = os.path.join(dirPath, filename)

    # Ensure that the path is under the correct folder. This is to thwart malicious URLs that might contain extra
    # slashes or '..'
    if os.path.commonprefix([dirPath, filePath]) != dirPath:
        return None

    if not os.path.isfile(filePath):
        return None

    try:
        return open(filePath, 'rb')
    except:
        return None

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
    renderer = pystache.Renderer(search_dirs=[resourcePath(TEMPLATES)], missing_tags='strict')

    def do_GET(self):
        if self.path == '/':
            (cmd, subPath) = ("index", '')
        else:
            (head, tail) = os.path.split(self.path.lstrip('/'))
            if head == 'static':
                self.sendStatic(tail)
                return

            (cmd, subPath) = (tail, '') if head == '' else (head, tail)

        methodName = 'cmd_' + cmd
        if not hasattr(self, methodName):
            self.send_error(404, cmd + " not implemented")
            return

        method = getattr(self, methodName)
        parts = urlparse.urlsplit(subPath)

        try:
            method(parts.path, urlparse.parse_qs(parts.query))
        except KeyboardInterrupt as ex:
            raise ex
        except:
            self.send_error(500, traceback.format_exc())

    def sendStatic(self, filename):
        fp = openResource(STATIC, filename)
        if not fp:
            self.send_error(404, "no such file")
            return

        with fp:
            type = mimetypes.guess_type(filename)

            # Send headers
            self.send_response(200)
            self.send_header("Content-type", type)
            fs = os.fstat(fp.fileno())
            self.send_header("Content-Length", str(fs[6]))
            self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
            self.end_headers()

            # Send bytes
            shutil.copyfileobj(fp, self.wfile)

    def sendTemplate(self, templateName, contentType = "text/html", **args):
        args["request"] = {
            "server_name": socket.gethostname()
        }

        print args

        content = self.renderer.render_name(templateName, args)
        self.send_response(200)
        self.send_header("Content-type", contentType)
        self.send_header("Content-Length", str(len(content)))
        self.end_headers()
        self.wfile.write(content)

    def cmd_version(self, path, query):
        self.send_response(200)
        self.send_header("Content-type", 'text/plain')
        self.end_headers()
        self.wfile.write("1")

    def cmd_index(self, path, query):
        self.sendTemplate("index.html")

if __name__ == '__main__':
    server = BaseHTTPServer.HTTPServer(('127.0.0.1', 8088), Handler)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    server.server_close()