def Control(self): """Handle POSTS.""" # Get the api version try: api_version = int( urlparse.parse_qs(self.path.split("?")[1])["api"][0]) except (ValueError, KeyError, IndexError): # The oldest api version we support if not specified. api_version = 3 try: if compatibility.PY2: content_length = self.headers.getheader("content-length") else: content_length = self.headers.get("content-length") if not content_length: raise IOError("No content-length header provided.") length = int(content_length) request_comms = rdf_flows.ClientCommunication.FromSerializedBytes( self._GetPOSTData(length)) # If the client did not supply the version in the protobuf we use the get # parameter. if not request_comms.api_version: request_comms.api_version = api_version # Reply using the same version we were requested with. responses_comms = rdf_flows.ClientCommunication( api_version=request_comms.api_version) # TODO: Python's documentation is just plain terrible and # does not explain what `client_address` exactly is or what type does it # have (because its Python, why would they bother) so just to be on the # safe side, we anticipate byte-string addresses in Python 2 and convert # that if needed. On Python 3 these should be always unicode strings, so # once support for Python 2 is dropped this branch can be removed. address = self.client_address[0] if compatibility.PY2 and isinstance(self.client_address[0], bytes): address = address.decode("ascii") source_ip = ipaddress.ip_address(address) if source_ip.version == 6: source_ip = source_ip.ipv4_mapped or source_ip request_comms.orig_request = rdf_flows.HttpRequest( timestamp=rdfvalue.RDFDatetime.Now(), raw_headers=str(self.headers), source_ip=str(source_ip)) source, nr_messages = self.server.frontend.HandleMessageBundles( request_comms, responses_comms) server_logging.LOGGER.LogHttpFrontendAccess( request_comms.orig_request, source=source, message_count=nr_messages) self.Send(responses_comms.SerializeToBytes()) except communicator.UnknownClientCertError: # "406 Not Acceptable: The server can only generate a response that is not # accepted by the client". This is because we can not encrypt for the # client appropriately. self.Send(b"Enrollment required", status=406)
def Control(self): """Handle POSTS.""" if not master.MASTER_WATCHER.IsMaster(): # We shouldn't be getting requests from the client unless we # are the active instance. stats_collector_instance.Get().IncrementCounter( "frontend_inactive_request_count", fields=["http"]) logging.info("Request sent to inactive frontend from %s", self.client_address[0]) # Get the api version try: api_version = int(cgi.parse_qs(self.path.split("?")[1])["api"][0]) except (ValueError, KeyError, IndexError): # The oldest api version we support if not specified. api_version = 3 try: content_length = self.headers.getheader("content-length") if not content_length: raise IOError("No content-length header provided.") length = int(content_length) request_comms = rdf_flows.ClientCommunication.FromSerializedString( self._GetPOSTData(length)) # If the client did not supply the version in the protobuf we use the get # parameter. if not request_comms.api_version: request_comms.api_version = api_version # Reply using the same version we were requested with. responses_comms = rdf_flows.ClientCommunication( api_version=request_comms.api_version) source_ip = ipaddr.IPAddress(self.client_address[0]) if source_ip.version == 6: source_ip = source_ip.ipv4_mapped or source_ip request_comms.orig_request = rdf_flows.HttpRequest( timestamp=rdfvalue.RDFDatetime.Now().AsMicrosecondsSinceEpoch( ), raw_headers=utils.SmartStr(self.headers), source_ip=utils.SmartStr(source_ip)) source, nr_messages = self.server.frontend.HandleMessageBundles( request_comms, responses_comms) server_logging.LOGGER.LogHttpFrontendAccess( request_comms.orig_request, source=source, message_count=nr_messages) self.Send(responses_comms.SerializeToString()) except communicator.UnknownClientCert: # "406 Not Acceptable: The server can only generate a response that is not # accepted by the client". This is because we can not encrypt for the # client appropriately. self.Send("Enrollment required", status=406)