def _get_module_with_soft_routing(self, module_name, version): """Uses soft-routing to find the specified module. Soft-routing is an attempt to match the production resolution order, which is slightly more permissive than the Modules API behavior. Here are the rules allowed: 1. If a module is requested that doesn't exist, use the default module. 2. If a module is requested that doesn't exist, and there is no default module, use any module. Args: module_name: The name of the module. version: The version id. Returns: Module object. Raises: request_info.ModuleDoesNotExistError: The module doesn't exist. request_info.VersionDoesNotExistError: The version doesn't exist. """ if not module_name or module_name not in self._module_name_to_module: if appinfo.DEFAULT_MODULE in self._module_name_to_module: module_name = appinfo.DEFAULT_MODULE elif self._module_name_to_module: # If there is no default module, but there are other modules, take any. # This is somewhat of a hack, and can be removed if we ever enforce the # existence of a default module. module_name = self._module_name_to_module.keys()[0] else: raise request_info.ModuleDoesNotExistError(module_name) if (version is not None and version != self._module_configurations[module_name].major_version): raise request_info.VersionDoesNotExistError() return self._module_name_to_module[module_name]
def _resolve_target(self, hostname, path): """Returns the module and instance that should handle this request. Args: hostname: A string containing the value of the host header in the request or None if one was not present. path: A string containing the path of the request. Returns: A tuple (_module, inst) where: _module: The module.Module that should handle this request. inst: The instance.Instance that should handle this request or None if the module's load balancing should decide on the instance. Raises: request_info.ModuleDoesNotExistError: if hostname is not known. """ if self._port == 80: default_address = self.host else: default_address = '%s:%s' % (self.host, self._port) if not hostname or hostname == default_address: return self._module_for_request(path), None default_address_offset = hostname.find(default_address) if default_address_offset > 0: prefix = hostname[:default_address_offset - 1] if '.' in prefix: raise request_info.ModuleDoesNotExistError(prefix) return self._get_module_with_soft_routing(prefix, None), None else: if ':' in hostname: port = int(hostname.split(':', 1)[1]) else: port = 80 try: _module, inst = self._port_registry.get(port) except KeyError: raise request_info.ModuleDoesNotExistError(hostname) if not _module: _module = self._module_for_request(path) return _module, inst
def _resolve_target(self, hostname, path): """Returns the module and instance that should handle this request. Args: hostname: A string containing the value of the host header in the request or None if one was not present. path: A string containing the path of the request. Returns: A tuple (_module, inst) where: _module: The module.Module that should handle this request. inst: The instance.Instance that should handle this request or None if the module's load balancing should decide on the instance. Raises: request_info.ModuleDoesNotExistError: if hostname is not known. """ if self._port == 80: default_address = self.host else: default_address = '%s:%s' % (self.host, self._port) if not hostname or hostname == default_address: return self._module_for_request(path), None default_address_offset = hostname.find(default_address) if default_address_offset > 0: prefix = hostname[:default_address_offset - 1] # The prefix should be 'module', but might be 'instance.version.module', # 'version.module', or 'instance.module'. These alternatives work in # production, but devappserver2 doesn't support running multiple versions # of the same module. All we can really do is route to the default # version of the specified module. if '.' in prefix: logging.warning('Ignoring instance/version in %s; multiple versions ' 'are not supported in devappserver.', prefix) module_name = prefix.split('.')[-1] return self._get_module_with_soft_routing(module_name, None), None else: if ':' in hostname: port = int(hostname.split(':', 1)[1]) else: port = 80 try: _module, inst = self._port_registry.get(port) except KeyError: raise request_info.ModuleDoesNotExistError(hostname) if not _module: _module = self._module_for_request(path) return _module, inst
def _get_module(self, module_name, version): if not module_name or module_name not in self._module_name_to_module: if 'default' in self._module_name_to_module: module_name = 'default' elif self._module_name_to_module: # If there is no default module, but there are other modules, take any. # This is somewhat of a hack, and can be removed if we ever enforce the # existence of a default module. module_name = self._module_name_to_module.keys()[0] else: raise request_info.ModuleDoesNotExistError(module_name) elif (version is not None and version != self._module_configurations[module_name].major_version): raise request_info.VersionDoesNotExistError() return self._module_name_to_module[module_name]
def get_default_version(self, _module): """Returns the default version for a module. Args: _module: A str containing the name of the module. Returns: A str containing the default version for the specified module. Raises: request_info.ModuleDoesNotExistError: The module does not exist. """ if _module in self._module_configurations: return self._module_configurations[_module].major_version else: raise request_info.ModuleDoesNotExistError(_module)
def get_module_by_name(self, _module): """Returns the module with the given name. Args: _module: A str containing the name of the module. Returns: The module.Module with the provided name. Raises: request_info.ModuleDoesNotExistError: The module does not exist. """ try: return self._module_name_to_module[_module] except KeyError: raise request_info.ModuleDoesNotExistError(_module)
def _get_module(self, module_name, version): """Attempts to find the specified module. Args: module_name: The name of the module. version: The version id. Returns: Module object. Raises: request_info.ModuleDoesNotExistError: The module doesn't exist. request_info.VersionDoesNotExistError: The version doesn't exist. """ if not module_name: module_name = appinfo.DEFAULT_MODULE if module_name not in self._module_name_to_module: raise request_info.ModuleDoesNotExistError() if (version is not None and version != self._module_configurations[module_name].major_version): raise request_info.VersionDoesNotExistError() return self._module_name_to_module[module_name]
def _resolve_target(self, hostname, path): """Returns the module and instance that should handle this request. Args: hostname: A string containing the value of the host header in the request or None if one was not present. path: A string containing the path of the request. Returns: A tuple (_module, inst) where: _module: The module.Module that should handle this request. inst: The instance.Instance that should handle this request or None if the module's load balancing should decide on the instance. Raises: request_info.ModuleDoesNotExistError: if hostname is not known. """ if self._port == 80: default_address = self.host else: default_address = '%s:%s' % (self.host, self._port) if not hostname or hostname == default_address: return self._module_for_request(path), None default_address_offset = hostname.find(default_address) if default_address_offset > 0: prefix = hostname[:default_address_offset - 1] # The prefix should be 'module', but might be 'instance.version.module', # 'version.module', or 'instance.module'. These alternatives work in # production, but devappserver2 doesn't support running multiple versions # of the same module. All we can really do is route to the default # version of the specified module. if '.' in prefix: logging.warning('Ignoring instance/version in %s; multiple versions ' 'are not supported in devappserver.', prefix) module_name = prefix.split('.')[-1] return self._get_module_with_soft_routing(module_name, None), None else: def get_port(hostname): # This will first check to see if hostname is an IPv6 address, then it # will fall back on the old-school method of looking for a colon # followed by numbers at the end. PORT_RE = re.compile( r"^\[[0-9a-fA-F:]+\]:(?P<port>[0-9]+)|.*:(?P<port2>[0-9]+)$") matched = PORT_RE.match(hostname) return matched and int(matched.group("port") or matched.group("port2")) _port = get_port(hostname) if _port is not None: port = _port else: port = 80 try: _module, inst = self._port_registry.get(port) except KeyError: raise request_info.ModuleDoesNotExistError(hostname) if not _module: _module = self._module_for_request(path) return _module, inst