コード例 #1
0
    def preprocessRequest(self):
        """Do any request processing that doesn't follow the normal
        resource lookup procedure. "OPTIONS *" is handled here, for
        example. This would also be the place to do any CONNECT
        processing."""

        # Always reject HTTP/1.0 - no clients should use it
        if self.clientproto == (1, 0):
            raise http.HTTPError(responsecode.BAD_REQUEST)

        if self.method == "OPTIONS" and self.uri == "*":
            response = http.Response(responsecode.OK)
            response.headers.setHeader('allow',
                                       ('GET', 'HEAD', 'OPTIONS', 'TRACE'))
            return response

        elif self.method == "POST":
            # Allow other methods to tunnel through using POST and a request header.
            # See http://code.google.com/apis/gdata/docs/2.0/basics.html
            if self.headers.hasHeader("X-HTTP-Method-Override"):
                intendedMethod = self.headers.getRawHeaders(
                    "X-HTTP-Method-Override")[0]
                if intendedMethod:
                    self.originalMethod = self.method
                    self.method = intendedMethod

        # This is where CONNECT would go if we wanted it
        return None
コード例 #2
0
 def render(self, req):
     if req.avatar.username == 'anonymous':
         if not self.sendOwnHeaders:
             raise http.HTTPError(responsecode.UNAUTHORIZED)
         else:
             return http.Response(
                 responsecode.UNAUTHORIZED,
                 {'www-authenticate': [('basic', {'realm': 'foo'})]})
     else:
         return super(NonAnonymousResource, self).render(req)
コード例 #3
0
    def _handleSegment(self, result, res, path, updatepaths):
        """Handle the result of a locateChild call done in _getChild."""

        newres, newpath = result
        # If the child resource is None then display a error page
        if newres is None:
            raise http.HTTPError(responsecode.NOT_FOUND)

        # If we got a deferred then we need to call back later, once the
        # child is actually available.
        if isinstance(newres, defer.Deferred):
            return newres.addCallback(lambda actualRes: self._handleSegment(
                (actualRes, newpath), res, path, updatepaths))

        if path:
            url = quote("/" + "/".join(path))
        else:
            url = "/"

        if newpath is StopTraversal:
            # We need to rethink how to do this.
            # if newres is res:
            return res
            # else:
            #    raise ValueError("locateChild must not return StopTraversal with a resource other than self.")

        newres = iweb.IResource(newres)
        if newres is res:
            assert newpath is not path, "URL traversal cycle detected when attempting to locateChild %r from resource %r." % (
                path, res)
            assert len(newpath) < len(path), "Infinite loop impending..."

        if updatepaths:
            # We found a Resource... update the request.prepath and postpath
            for _ in xrange(len(path) - len(newpath)):
                self.prepath.append(self.postpath.pop(0))
            url = quote("/" + "/".join(self.prepath) +
                        ("/" if self.prepath and self.prepath[-1] else ""))
            self._rememberResource(newres, url)
        else:
            try:
                previousURL = self.urlForResource(res)
                url = quote(previousURL + path[0] +
                            ("/" if path[0] and len(path) > 1 else ""))
                self._rememberResource(newres, url)
            except NoURLForResourceError:
                pass

        child = self._getChild(None, newres, newpath, updatepaths=updatepaths)

        return child
コード例 #4
0
    def _fixupURLParts(self):
        _ignore_hostaddr, secure = self.chanRequest.getHostInfo()
        if not self.scheme:
            self.scheme = ('http', 'https')[secure]

        if self.host:
            self.host, self.port = http.splitHostPort(self.scheme, self.host)
            self.scheme = ('http', 'https')[self._schemeFromPort(self.port)]
        else:
            # If GET line wasn't an absolute URL
            host = self.headers.getHeader('host')
            if host:
                self.host, self.port = http.splitHostPort(self.scheme, host)
                self.scheme = ('http',
                               'https')[self._schemeFromPort(self.port)]
            else:
                # When no hostname specified anywhere, either raise an
                # error, or use the interface hostname, depending on
                # protocol version
                if self.clientproto >= (1, 1):
                    raise http.HTTPError(responsecode.BAD_REQUEST)

                # Always require host header even for HTTP/1.0
                raise http.HTTPError(responsecode.BAD_REQUEST)
コード例 #5
0
def parsePOSTData(request,
                  maxMem=100 * 1024,
                  maxFields=1024,
                  maxSize=10 * 1024 * 1024):
    """
    Parse data of a POST request.

    @param request: the request to parse.
    @type request: L{txweb2.http.Request}.
    @param maxMem: maximum memory used during the parsing of the data.
    @type maxMem: C{int}
    @param maxFields: maximum number of form fields allowed.
    @type maxFields: C{int}
    @param maxSize: maximum size of file upload allowed.
    @type maxSize: C{int}

    @return: a deferred that will fire when the parsing is done. The deferred
        itself doesn't hold a return value, the request is modified directly.
    @rtype: C{defer.Deferred}
    """
    if request.stream.length == 0:
        return defer.succeed(None)

    ctype = request.headers.getHeader('content-type')

    if ctype is None:
        return defer.succeed(None)

    def updateArgs(data):
        args = data
        request.args.update(args)

    def updateArgsAndFiles(data):
        args, files = data
        request.args.update(args)
        request.files.update(files)

    def error(f):
        f.trap(fileupload.MimeFormatError)
        raise http.HTTPError(
            http.StatusResponse(responsecode.BAD_REQUEST, str(f.value)))

    if (ctype.mediaType == 'application'
            and ctype.mediaSubtype == 'x-www-form-urlencoded'):
        d = fileupload.parse_urlencoded(request.stream)
        d.addCallbacks(updateArgs, error)
        return d
    elif (ctype.mediaType == 'multipart'
          and ctype.mediaSubtype == 'form-data'):
        boundary = ctype.params.get('boundary')
        if boundary is None:
            return defer.fail(
                http.HTTPError(
                    http.StatusResponse(
                        responsecode.BAD_REQUEST,
                        "Boundary not specified in Content-Type.")))
        d = fileupload.parseMultipartFormData(request.stream, boundary, maxMem,
                                              maxFields, maxSize)
        d.addCallbacks(updateArgsAndFiles, error)
        return d
    else:
        return defer.fail(
            http.HTTPError(
                http.StatusResponse(
                    responsecode.BAD_REQUEST, "Invalid content-type: %s/%s" %
                    (ctype.mediaType, ctype.mediaSubtype))))
コード例 #6
0
    def locateResource(self, url):
        """
        Looks up the resource with the given URL.
        @param uri: The URL of the desired resource.
        @return: a L{Deferred} resulting in the L{IResource} at the
            given URL or C{None} if no such resource can be located.
        @raise HTTPError: If C{url} is not a URL on the site that this
            request is being applied to.  The contained response will
            have a status code of L{responsecode.BAD_GATEWAY}.
        @raise HTTPError: If C{url} contains a query or fragment.
            The contained response will have a status code of
            L{responsecode.BAD_REQUEST}.
        """
        if url is None:
            return defer.succeed(None)

        #
        # Parse the URL
        #
        (_ignore_scheme, _ignore_host, path, query, fragment) = urlsplit(url)

        if query or fragment:
            raise http.HTTPError(
                http.StatusResponse(
                    responsecode.BAD_REQUEST,
                    "URL may not contain a query or fragment: %s" % (url, )))

        # Look for cached value
        cached = self._resourcesByURL.get(path, None)
        if cached is not None:
            return defer.succeed(cached)

        segments = unquote(path).split("/")
        assert segments[0] == "", "URL path didn't begin with '/': %s" % (
            path, )

        # Walk the segments up to see if we can find a cached resource to start from
        preSegments = segments[:-1]
        postSegments = segments[-1:]
        cachedParent = None
        while (len(preSegments)):
            parentPath = "/".join(preSegments) + "/"
            cachedParent = self._resourcesByURL.get(parentPath, None)
            if cachedParent is not None:
                break
            else:
                postSegments.insert(0, preSegments.pop())

        if cachedParent is None:
            cachedParent = self.site.resource
            postSegments = segments[1:]

        def notFound(f):
            f.trap(http.HTTPError)
            if f.value.response.code != responsecode.NOT_FOUND:
                return f
            return None

        d = defer.maybeDeferred(self._getChild,
                                None,
                                cachedParent,
                                postSegments,
                                updatepaths=False)
        d.addCallback(self._rememberResource, path)
        d.addErrback(notFound)
        return d
コード例 #7
0
 def error(f):
     f.trap(fileupload.MimeFormatError)
     raise http.HTTPError(
         http.StatusResponse(responsecode.BAD_REQUEST, str(f.value)))
コード例 #8
0
ファイル: static.py プロジェクト: redtailtech/calendarserver
#
#     def __init__(self, path):
#         self.path = path
#
#     def renderHTTP(self, request):
#         request.startedWriting = 1
#         return File(self.path)
#
#     def locateChild(self, request):
#         return None, ()

##
# Utilities
##

dangerousPathError = http.HTTPError(
    responsecode.NOT_FOUND)  #"Invalid request URL."


def isDangerous(path):
    return path == '..' or '/' in path or os.sep in path


def addSlash(request):
    return "http%s://%s%s/" % (request.isSecure() and 's'
                               or '', request.getHeader("host"),
                               (request.uri.split('?')[0]))


def loadMimeTypes(mimetype_locations=['/etc/mime.types']):
    """
    Multiple file locations containing mime-types can be passed as a list.
コード例 #9
0
 def _respond(response):
     return failure.Failure(http.HTTPError(response))