def run(self): processing_start_time = time.time() self.root = "response" self.response = {} if not self.headers: return self.failure("Header 'host' required for all requests.") hostname = self.headers["host"].partition(":")[0] hostname_matches = re.findall("(\w+).(rapidrec.com|localhost)", hostname) if not hostname_matches: return self.failure( "Could not determine sitename. Please use " + "[sitename].rapidrec.com for all requests." ) else: self.sitename = hostname_matches[0][0] # Check the validity of the sitename try: self.sitename = filters.check_name(self.sitename, 32) except (filters.TypeError, filters.RangeError): return self.failure("Invalid site: %s" % self.sitename) # Check that the site exists by instantiating RapidRecSite try: rrsite = RapidRecSite(self.sitename) except RapidRecSite.ConnectionError: return self.failure("Unknown site: %s" % self.sitename) # Check the remote IP against the list of allowed IPs remoteip = self.request.getClientIP() # Break a comma-separated string into a list, with one tuple per IP ('IP', unused, 'cidr') try: iplist = str(rrsite.get_config_field("ip_allow")).split(",") except RapidRecSite.ConfigFieldNotFound: iplist = ["0.0.0.0/0"] while "" in iplist: iplist.remove("") iplist.append("127.0.0.1") if self.sitename.startswith("test"): iplist.append("68.9.232.69") # for development only if not ipfilter.is_ip_in_list(remoteip, iplist): return self.failure("Access forbidden from your IP: %s is not in { %s }" % (remoteip, ", ".join(iplist))) # At this point, the request is considered authentic. # We now proceed to process the request. # Find the path list and query (if any) by breaking up the QUERY_STRING # (fullpath, unused, query) = self.path.partition('?') fullpath = self.path path = fullpath.split("/") # Remove empty strings from the path list caused # by duplicate and unnecessary slashes in the path while "" in path: path.remove("") depth = 0 args = {} if self.method == "post": if "content-length" not in self.headers: return self.failure("content-length required when POSTing") self.contentLength = int(self.headers["content-length"]) self.request.content.seek(0, 0) args["postdata"] = self.request.content.read(self.contentLength) elif self.method != "get": return self.failure("Method not supported. Only GET and POST operations are allowed.") objtypes = ["users", "items", "movies"] try: if len(path) <= depth: raise (res.errors.UnimplementedError) elif path[depth] == "config": # /config... depth += 1 raise (res.errors.UnimplementedError) elif path[depth] in objtypes: # /objs... args["type"] = "user" if path[depth] == "users" else "item" depth += 1 if len(path) <= depth: # /objs Handler = res.objs.Handler else: # /objs/{obj}... args["name"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj} Handler = res.obj.Handler elif path[depth] in objtypes: # /objs/{obj}/objs... args["tgt_type"] = "user" if path[depth] == "users" else "item" depth += 1 if len(path) <= depth: # /objs/{obj}/objs raise (res.errors.UnimplementedError) else: # /objs/{obj}/objs/{obj}... args["tgt_name"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/objs/{obj} Handler = res.objobj.Handler else: # /objs/{obj}/objs/{obj}/{resource}... args["resource"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/objs/{obj}/{resource} Handler = res.objobjres.Handler else: # /objs/{obj}/objs/{obj}/{resource}/... raise (res.errors.UnsupportedError) else: # /objs/{obj}/resource args["resource"] = path[depth] depth += 1 if len(path) <= depth: # /objs/{obj}/{resource} Handler = res.objres.Handler else: # /objs/{obj}/{resource}/... raise (res.errors.UnsupportedError) else: # /{not-supported}... raise (res.errors.UnsupportedError) # Here is where we actually service queries that look valid so far handler = Handler(rrsite, self.response, self.method, self.request.args, args) handler.run() xmlext.set_status(self.response, "OKAY", "Query completed successfully.") except res.errors.ContentLengthMissingError: xmlext.set_status(self.response, "ERROR", "Content-length missing.") except res.errors.MethodError: xmlext.set_status(self.response, "ERROR", "Method not supported.") except res.errors.QueryError: xmlext.set_status(self.response, "ERROR", "Invalid query.") except res.errors.UnsupportedError: xmlext.set_status(self.response, "ERROR", "Resource not supported.") except res.errors.UnimplementedError: xmlext.set_status(self.response, "ERROR", "Resource not implemented.") except res.errors.PostError: xmlext.set_status(self.response, "ERROR", "Could not understand request body.") except res.errors.IdError: xmlext.set_status(self.response, "ERROR", "Invalid user or item identifier.") except res.errors.UnknownError: xmlext.set_status(self.response, "ERROR", "Unknown Error.") processing_finish_time = time.time() processing_time_elapsed = processing_finish_time - processing_start_time treexml.insert_node(self.response, "system_usage", "%f" % processing_time_elapsed) # print response self.respXML() self.send(treexml.encode(self.root, self.response)) return self.finishreq()
def unimplemented(str): xmlext.set_status(response, "ERROR", "Resource not yet implemented.")
def failure(self, text): self.respXML() xmlext.set_status(self.response, "DENY", text) self.send(treexml.encode(self.root, self.response)) return self.finishreq()
def unsupported(str): xmlext.set_status(response, "ERROR", "Resource not supported.")