Beispiel #1
0
def GenApiConfig(service_class_names):
    """Write an API configuration for endpoints annotated ProtoRPC services.

  Args:
    service_class_names: A list of fully qualified ProtoRPC service classes.

  Raises:
    TypeError: If any service classes don't inherit from remote.Service.
    messages.DefinitionNotFoundError: If a service can't be found.

  Returns:
    A map from service names to a string containing the API configuration of the
      service in JSON format.
  """
    service_map = {}
    generator = api_config.ApiConfigGenerator()
    for service_class_name in service_class_names:
        module_name, base_service_class_name = service_class_name.rsplit(
            '.', 1)
        module = __import__(module_name, fromlist=base_service_class_name)
        service = getattr(module, base_service_class_name)
        if issubclass(service, remote.Service):
            service_map[
                service_class_name] = generator.pretty_print_config_to_json(
                    service)
        else:
            raise TypeError('%s is not a ProtoRPC service' %
                            service_class_name)

    return service_map
Beispiel #2
0
    def __init__(self, api_services, **kwargs):
        """Initialize an _ApiServer instance.

    The primary function of this method is to set up the WSGIApplication
    instance for the service handlers described by the services passed in.
    Additionally, it registers each API in ApiConfigRegistry for later use
    in the BackendService.getApiConfigs() (API config enumeration service).

    Args:
      api_services: List of protorpc.remote.Service classes implementing the API
      **kwargs: Passed through to protorpc.wsgi.service.service_handlers except:
        protocols - ProtoRPC protocols are not supported, and are disallowed.
        restricted - If True or unset, the API will only be allowed to serve to
          Google's API serving infrastructure once deployed.  Set to False to
          allow other clients.  Under dev_appserver, all clients are accepted.
          NOTE! Under experimental launch, this is not a secure restriction and
          other authentication mechanisms *must* be used to control access to
          the API.  The restriction is only intended to notify developers of
          a possible upcoming feature to securely restrict access to the API.

    Raises:
      TypeError: if protocols are configured (this feature is not supported).
      ApiConfigurationError: if there's a problem with the API config.
    """
        protorpc_services = []
        generator = api_config.ApiConfigGenerator()
        self.api_config_registry = api_backend_service.ApiConfigRegistry()
        api_name_version_map = {}
        for service in api_services:
            key = (service.api_info.name, service.api_info.version)
            services = api_name_version_map.setdefault(key, [])
            if service in services:
                raise api_config.ApiConfigurationError(
                    'Can\'t add the same class to an API twice: %s' %
                    service.__name__)
            services.append(service)

        for services in api_name_version_map.values():
            config_file = generator.pretty_print_config_to_json(services)

            self.api_config_registry.register_spi(config_file)
            for api_service in services:
                protorpc_class_name = api_service.__name__
                root = self.__SPI_PREFIX + protorpc_class_name
                if not any(service[0] == root or service[1] == api_service
                           for service in protorpc_services):
                    protorpc_services.append((root, api_service))

        backend_service = api_backend_service.BackendServiceImpl.new_factory(
            self.api_config_registry, _get_app_revision())
        protorpc_services.insert(
            0, (self.__BACKEND_SERVICE_ROOT, backend_service))

        if 'protocols' in kwargs:
            raise TypeError('__init__() got an unexpected keyword argument '
                            "'protocols'")
        self.restricted = kwargs.pop('restricted', True)
        self.service_app = wsgi_service.service_mappings(
            protorpc_services, **kwargs)
Beispiel #3
0
def GenApiConfig(service_class_names, generator=None, hostname=None):
    """Write an API configuration for endpoints annotated ProtoRPC services.

  Args:
    service_class_names: A list of fully qualified ProtoRPC service classes.
    generator: An generator object that produces API config strings using its
      pretty_print_config_to_json method.
    hostname: A string hostname which will be used as the default version
      hostname. If no hostname is specificied in the @endpoints.api decorator,
      this value is the fallback. Defaults to None.

  Raises:
    TypeError: If any service classes don't inherit from remote.Service.
    messages.DefinitionNotFoundError: If a service can't be found.

  Returns:
    A map from service names to a string containing the API configuration of the
      service in JSON format.
  """

    api_service_map = collections.OrderedDict()
    for service_class_name in service_class_names:
        module_name, base_service_class_name = service_class_name.rsplit(
            '.', 1)
        module = __import__(module_name, fromlist=base_service_class_name)
        service = getattr(module, base_service_class_name)
        if not (isinstance(service, type)
                and issubclass(service, remote.Service)):
            raise TypeError('%s is not a ProtoRPC service' %
                            service_class_name)

        services = api_service_map.setdefault(
            (service.api_info.name, service.api_info.version), [])
        services.append(service)

    service_map = collections.OrderedDict()
    generator = generator or api_config.ApiConfigGenerator()
    for api_info, services in api_service_map.iteritems():

        hostname = services[0].api_info.hostname or hostname

        service_map['%s-%s' %
                    api_info] = generator.pretty_print_config_to_json(
                        services, hostname=hostname)

    return service_map
Beispiel #4
0
    def __register_services(api_name_version_map, api_config_registry):
        """Register & return a list of each SPI URL and class that handles that URL.

    This finds every service class in api_name_version_map, registers it with
    the given ApiConfigRegistry, builds the SPI url for that class, and adds
    the URL and its factory to a list that's returned.

    Args:
      api_name_version_map: A mapping from (api name, api version) to a list of
        service factories, as returned by __create_name_version_map.
      api_config_registry: The ApiConfigRegistry where service classes will
        be registered.

    Returns:
      A list of (SPI URL, service_factory) for each service class in
      api_name_version_map.

    Raises:
      ApiConfigurationError: If a Service class appears more than once
        in api_name_version_map.  This could happen if one class is used to
        implement multiple APIs.
    """
        generator = api_config.ApiConfigGenerator()
        protorpc_services = []
        for service_factories in api_name_version_map.itervalues():
            service_classes = [
                service_factory.service_class
                for service_factory in service_factories
            ]
            config_file = generator.pretty_print_config_to_json(
                service_classes)
            api_config_registry.register_spi(config_file)

            for service_factory in service_factories:
                protorpc_class_name = service_factory.service_class.__name__
                root = _ApiServer.__SPI_PREFIX + protorpc_class_name
                if any(service_map[0] == root
                       or service_map[1] == service_factory
                       for service_map in protorpc_services):
                    raise api_config.ApiConfigurationError(
                        'Can\'t reuse the same class in multiple APIs: %s' %
                        protorpc_class_name)
                protorpc_services.append((root, service_factory))
        return protorpc_services