Example #1
0
    def __call__(self, environ, start_response):
        """Main WSGI callable.
        """

        # Translate the request to the filesystem.
        # ========================================

        fspath = translate(self.config.paths.root, environ['PATH_INFO'])
        if self.config.paths.__ is not None:
            if fspath.startswith(self.config.paths.__):
                raise Response(404)  # protect magic directory
        environ['PATH_TRANSLATED'] = fspath

        # Dispatch to a WSGI app or an aspen handler.
        # ===========================================

        app = self.get_app(environ)  # 301
        if app is not None:  # app
            response = app(environ, start_response)  # WSGI
        else:  # handler
            if not exists(fspath):
                raise Response(404)
            check_trailing_slash(environ)
            fspath = find_default(self.config.defaults, fspath)  # 403

            environ['PATH_TRANSLATED'] = fspath
            environ['aspen.website'] = self
            fp = environ['aspen.fp'] = open(fspath)

            handler = self.get_handler(fp)
            fp.seek(0)
            response = handler.handle(environ, start_response)  # WSGI

        return response
Example #2
0
def check_trailing_slash(environ):
    """Given a WSGI environ, return None or raise 301.

    environ must have PATH_TRANSLATED set in addition to PATH_INFO, which
    latter is required by the spec.

    """
    fs = environ['PATH_TRANSLATED']
    url = environ['PATH_INFO']
    if isdir(fs) and not url.endswith('/'):
        environ['PATH_INFO'] += '/'
        response = Response(301)
        response.headers['Location'] = full_url(environ)
        raise response
Example #3
0
def pyscript(environ, start_response):
    """Execute the script pseudo-CGI-style.
    """

    context = dict(request=environ)
    context['response'] = Response()
    context['__file__'] = environ['aspen.fp'].name

    fp = environ['aspen.fp']
    del environ['aspen.fp']
    try:
        exec fp in context
    except SystemExit:
        pass
    return environ['response']
Example #4
0
def find_default(defaults, path):
    """Given a list of defaults and a path, return a filepath or raise 403.

    If the path isn't a directory, simply return it.

    """
    default = None
    if isdir(path):
        for name in defaults:
            _path = join(path, name)
            if isfile(_path):
                default = _path
                break
        if default is None:
            raise Response(403)
        path = default
    return path
Example #5
0
 def get_app(self, environ):
     """Given a WSGI environ, return the first matching app.
     """
     app = None
     test_path = environ['PATH_INFO']
     if not test_path.endswith('/'):
         test_path += '/'
     for app_urlpath, _app in self.config.apps:
         if test_path.startswith(app_urlpath):
             environ['PATH_TRANSLATED'] = translate(self.config.paths.root,
                                                    app_urlpath)
             if not isdir(environ['PATH_TRANSLATED']):
                 raise Response(404)
             if app_urlpath.endswith('/'):
                 check_trailing_slash(environ)
             app = _app
             break
     if app is None:
         log.debug("No app found for '%s'" % environ['PATH_INFO'])
     return app
Example #6
0
def static(environ, start_response):
    """Serve a static file off of the filesystem.

    In staging and deployment modes, we honor any 'If-Modified-Since'
    header, an HTTP header used for caching.

    """

    path = environ['PATH_TRANSLATED']
    ims = environ.get('HTTP_IF_MODIFIED_SINCE', '')

    # Get basic info from the filesystem and start building a response.
    # =================================================================

    stats = os.stat(path)
    mtime = stats[stat.ST_MTIME]
    size = stats[stat.ST_SIZE]
    content_type = mimetypes.guess_type(path)[0] or 'text/plain'
    response = Response(200)

    # Support 304s, but only in deployment mode.
    # ==========================================

    if mode.stprod:
        if ims:
            mod_since = rfc822.parsedate(ims)
            last_modified = time.gmtime(mtime)
            if last_modified[:6] <= mod_since[:6]:
                response.code = 304

    # Finish building the response and return it.
    # ===========================================

    response.headers['Last-Modified'] = rfc822.formatdate(mtime)
    response.headers['Content-Type'] = content_type
    response.headers['Content-Length'] = size
    if response.code != 304:
        response.body = open(path).read()
    return response
Example #7
0
def HTTP404(environ, start_response):
    raise Response(404)