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 None # # Parse the URL # (scheme, 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, ))) # The caller shouldn't be asking a request on one server to lookup a # resource on some other server. if (scheme and scheme != self.scheme) or ( host and host != self.headers.getHeader("host")): raise http.HTTPError( http.StatusResponse( responsecode.BAD_GATEWAY, "URL is not on this site (%s://%s/): %s" % (scheme, self.headers.getHeader("host"), url))) segments = path.split("/") assert segments[0] == "", "URL path didn't begin with '/': %s" % ( path, ) segments = map(unquote, 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, self.site.resource, segments, updatepaths=False) d.addCallback(self._rememberResource, path) d.addErrback(notFound) return d
def locateChild(self, request, segments): fnp = self.child(segments[0]) if not fnp.exists(): raise http.HTTPError(responsecode.NOT_FOUND) elif fnp.isdir(): return CGIDirectory(fnp.path), segments[1:] else: return CGIScript(fnp.path), segments[1:] return None, ()
def locateChild(self, req, segments): scheme = req.headers.getRawHeaders('x-app-scheme') if self.sendsRealHost: host = req.headers.getRawHeaders('host') else: host = req.headers.getRawHeaders('x-forwarded-host') app_location = req.headers.getRawHeaders('x-app-location') remote_ip = req.headers.getRawHeaders('x-forwarded-for') if not (host and remote_ip): if not host: warnings.warn( ("No host was obtained either from Host or " "X-Forwarded-Host headers. If your proxy does not " "send either of these headers use VHostURIRewrite. " "If your proxy sends the real host as the Host header " "use " "AutoVHostURIRewrite(resrc, sendsRealHost=True)")) # some header unspecified => Error raise http.HTTPError(responsecode.BAD_REQUEST) host = host[0] remote_ip = remote_ip[0] if app_location: app_location = app_location[0] else: app_location = '/' if scheme: scheme = scheme[0] else: scheme='http' req.host, req.port = http.splitHostPort(scheme, host) req.scheme = scheme req.remoteAddr = address.IPv4Address('TCP', remote_ip, 0) req.prepath = app_location[1:].split('/')[:-1] req.path = '/'+('/'.join([urllib.quote(s, '') for s in (req.prepath + segments)])) return self.resource, segments
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: self._rememberResource(res, url) 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 not newpath is 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 x in xrange(len(path) - len(newpath)): self.prepath.append(self.postpath.pop(0)) child = self._getChild(None, newres, newpath, updatepaths=updatepaths) self._rememberResource(child, url) return child
def _fixupURLParts(self): 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) 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) 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) self.host = hostaddr.host self.port = hostaddr.port
def parsePOSTData(request): if request.stream.length == 0: return defer.succeed(None) parser = 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(responsecode.BAD_REQUEST) 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 failure.Failure( fileupload.MimeFormatError( "Boundary not specified in Content-Type.")) d = fileupload.parseMultipartFormData(request.stream, boundary) d.addCallbacks(updateArgsAndFiles, error) return d else: raise http.HTTPError(responsecode.BAD_REQUEST)
# # 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. The files will be sourced in that order, overriding mime-types from the files sourced beforehand, but only if a new entry explicitly overrides
def error(f): f.trap(fileupload.MimeFormatError) raise http.HTTPError(responsecode.BAD_REQUEST)