def _resource_located(self, result, request, response, old_res, credentials, old_loc, old_rem): if (result is None) or (isinstance(result, tuple) and (result[0] is None)): self.log("No resource found for sub-path '%s'", http.tuple2path(old_rem)) raise http.NotFoundError() if isinstance(result, tuple): if (len(result) < 1) or (len(result) > 3): raise http.InternalServerError("Invalid Resource Result") resource = result[0] if isinstance(server, defer.Deferred): resource.addCallback(lambda r: (r,) + result[1:]) resource.addCallback(self._resource_located, request, response, old_res, credentials, old_loc, old_rem) return resource resource = IWebResource(resource) if len(result) == 1: new_rem = () new_loc = old_loc + old_rem elif len(result) < 3: new_rem = ((len(result) > 1) and result[1]) or () delta = len(old_rem) - len(new_rem) if delta > 0: new_loc = old_loc + old_rem[:delta] else: new_loc = old_loc else: new_loc = result[2] new_rem = result[3] else: resource = IWebResource(result) new_rem = () new_loc = old_loc + old_rem if len(new_rem) > 0: # Still not a leaf, continue self.log( "Intermediary resource %s found for sub-path '%s' " "with remaining path '%s'", resource, http.tuple2path(new_loc), http.tuple2path(new_rem), ) return self._process_resource(request, response, resource, credentials, new_loc, new_rem) else: # We found the leaf self.log("resource %s found for sub-path '%s'", resource, http.tuple2path(new_loc)) return self._start_rendering(request, response, resource, credentials, new_loc)
def _locate_resource(self, request, response, resource, credentials, location, remaining): self.log("Locating resource for sub-path '%s'", http.tuple2path(remaining)) d = resource.locate_resource(request, location, tuple(remaining)) if isinstance(d, defer.Deferred): return d.addCallback(self._resource_located, request, response, resource, credentials, location, remaining) return self._resource_located(d, request, response, resource, credentials, location, remaining)
def _authenticate_resource(self, request, response, resource, credentials, location, continuation, *args): authenticator = resource.authenticator or self._authenticator if authenticator: self.log("Authenticating request %s for path '%s' with %s", request, http.tuple2path(location), resource) try: d = authenticator.authenticate(request, credentials, location) if isinstance(d, defer.Deferred): args = (request, response, resource, credentials, location, continuation, args) d.addCallbacks( self._got_authentication_result, self._authentication_failed, callbackArgs=args, errbackArgs=args, ) return d except: self._authentication_failed( Failure(), request, response, resource, credentials, location, continuation, args ) else: return self._got_authentication_result( d, request, response, resource, credentials, location, continuation, args ) return continuation(request, response, resource, credentials, location, *args)
def _got_authorization(self, authorized, request, response, resource, location): if not authorized: self.log( "Request %s not authorized for resource %s " "with path '%s'", request, resource, http.tuple2path(location), ) raise http.ForbiddenError("Resource Access Forbidden") self.log("Request %s authorized for resource %s with path '%s'", request, resource, http.tuple2path(location)) return self._render_resource(request, response, resource, location)
def action_GET(self, request, response, location): rel_loc = request.context.get("rel_loc") if rel_loc is None: raise http.NotFoundError() rel_path = http.tuple2path(rel_loc) full_path = os.path.join(self._root_path, rel_path) res_path = os.path.realpath(full_path) if not res_path.startswith(self._root_path): raise http.ForbiddenError() if os.path.isdir(res_path): raise http.ForbiddenError() if not os.path.isfile(res_path): raise http.NotFoundError() rst = os.stat(res_path) # FIXME: Caching Policy, should be extracted to a ICachingPolicy cache_control_header = request.get_header("cache-control") or "" pragma_header = request.get_header("pragma") or "" cache_control = http.parse_header_values(cache_control_header) pragma = http.parse_header_values(pragma_header) if not (u"no-cache" in cache_control or u"no-cache" in pragma): if u"max-age" in cache_control: max_age = int(cache_control[u"max-age"]) if max_age == 0 or (time.time() - rst.st_mtime) < max_age: response.set_status(http.Status.NOT_MODIFIED) return length = rst.st_size mime_type, content_encoding = self._mime_types.guess_type(res_path) mime_type = mime_type or "application/octet-stream" response.set_length(length) response.set_mime_type(mime_type) response.set_header("connection", "close") if content_encoding is not None: response.set_header("content-encoding", content_encoding) try: res = open(res_path, "rb") except IOError: raise http.ForbiddenError() response.do_not_cache() return threads.deferToThread(self._write_resource, #@UndefinedVariable response, res)
def _authorize_rendering(self, request, response, resource, credentials, location): response._set_location(location) authorizer = resource.authorizer or self._authorizer if authorizer: self.log("Authorizing request %s for path '%s'", request, http.tuple2path(location)) d = authorizer.authorize(request, credentials, location) if isinstance(d, defer.Deferred): args = (request, response, resource, location) d.addCallbacks(self._got_authorization, self._authorization_failed, callbackArgs=args, errbackArgs=args) return d return self._got_authorization(d, request, response, resource, location) return self._render_resource(request, response, resource, location)
def locate_resource(self, request, location, remaining): request_host = request.get_header('host') if request_host is not None: if ':' in request_host: request_host = request_host.split(":", 1)[0] if request_host != self.hostname: new_uri = "%s://%s:%s%s" % ( request.scheme.name.lower(), self.hostname, self.port, http.tuple2path(location + remaining)) return Redirect(new_uri) if self._static and remaining[0] == u"static": return self._static, remaining[1:] return self._build_root(request), remaining
def check(tup, encoding="utf8"): inter = http.tuple2path(tup, encoding=encoding) result = http.path2tuple(inter, encoding=encoding) self.assertEqual(result, tup)
def t2p(tup, expected, encoding="utf8"): result = http.tuple2path(tup, encoding=encoding) self.assertEqual(result, expected)
def check(tup, expected): result = http.tuple2path(tup) self.assertEqual(result, expected)
def make_model_address(self, location): host, port = location[0] path = "/" + http.tuple2path(location[1:]) return http.compose(host=host, port=port, path=path)
def make_model_address(self, location): host, port = location[0] path = "/" + http.tuple2path(location[1:]) return http.compose(host=host, port=port, path=path, query=http.compose_qs(self.arguments), scheme=self.scheme)
def _render_resource(self, request, response, resource, location): self.log("Rendering path '%s' for request %s", http.tuple2path(location), request) d = resource.render_resource(request, response, location) if isinstance(d, defer.Deferred): return d.addCallback(self._resource_rendered, request, response) return self._resource_rendered(d, request, response)
def make_model_address(self, location): return '/' + http.tuple2path(location)