| Index: tools/telemetry/third_party/gsutilz/third_party/protorpc/protorpc/wsgi/service.py
|
| diff --git a/tools/telemetry/third_party/gsutilz/third_party/protorpc/protorpc/wsgi/service.py b/tools/telemetry/third_party/gsutilz/third_party/protorpc/protorpc/wsgi/service.py
|
| deleted file mode 100755
|
| index bc1377e93546f0f731f8d819d51f2444b489e9bf..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/third_party/gsutilz/third_party/protorpc/protorpc/wsgi/service.py
|
| +++ /dev/null
|
| @@ -1,268 +0,0 @@
|
| -#!/usr/bin/env python
|
| -#
|
| -# Copyright 2011 Google Inc.
|
| -#
|
| -# Licensed under the Apache License, Version 2.0 (the "License");
|
| -# you may not use this file except in compliance with the License.
|
| -# You may obtain a copy of the License at
|
| -#
|
| -# http://www.apache.org/licenses/LICENSE-2.0
|
| -#
|
| -# Unless required by applicable law or agreed to in writing, software
|
| -# distributed under the License is distributed on an "AS IS" BASIS,
|
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -# See the License for the specific language governing permissions and
|
| -# limitations under the License.
|
| -#
|
| -
|
| -"""ProtoRPC WSGI service applications.
|
| -
|
| -Use functions in this module to configure ProtoRPC services for use with
|
| -WSGI applications. For more information about WSGI, please see:
|
| -
|
| - http://wsgi.org/wsgi
|
| - http://docs.python.org/library/wsgiref.html
|
| -"""
|
| -import six
|
| -
|
| -__author__ = 'rafek@google.com (Rafe Kaplan)'
|
| -
|
| -import cgi
|
| -import six.moves.http_client
|
| -import logging
|
| -import re
|
| -
|
| -from .. import messages
|
| -from .. import registry
|
| -from .. import remote
|
| -from .. import util
|
| -from . import util as wsgi_util
|
| -
|
| -__all__ = [
|
| - 'DEFAULT_REGISTRY_PATH',
|
| - 'service_app',
|
| -]
|
| -
|
| -_METHOD_PATTERN = r'(?:\.([^?]+))'
|
| -_REQUEST_PATH_PATTERN = r'^(%%s)%s$' % _METHOD_PATTERN
|
| -
|
| -_HTTP_BAD_REQUEST = wsgi_util.error(six.moves.http_client.BAD_REQUEST)
|
| -_HTTP_NOT_FOUND = wsgi_util.error(six.moves.http_client.NOT_FOUND)
|
| -_HTTP_UNSUPPORTED_MEDIA_TYPE = wsgi_util.error(six.moves.http_client.UNSUPPORTED_MEDIA_TYPE)
|
| -
|
| -DEFAULT_REGISTRY_PATH = '/protorpc'
|
| -
|
| -
|
| -@util.positional(2)
|
| -def service_mapping(service_factory, service_path=r'.*', protocols=None):
|
| - """WSGI application that handles a single ProtoRPC service mapping.
|
| -
|
| - Args:
|
| - service_factory: Service factory for creating instances of service request
|
| - handlers. Either callable that takes no parameters and returns a service
|
| - instance or a service class whose constructor requires no parameters.
|
| - service_path: Regular expression for matching requests against. Requests
|
| - that do not have matching paths will cause a 404 (Not Found) response.
|
| - protocols: remote.Protocols instance that configures supported protocols
|
| - on server.
|
| - """
|
| - service_class = getattr(service_factory, 'service_class', service_factory)
|
| - remote_methods = service_class.all_remote_methods()
|
| - path_matcher = re.compile(_REQUEST_PATH_PATTERN % service_path)
|
| -
|
| - def protorpc_service_app(environ, start_response):
|
| - """Actual WSGI application function."""
|
| - path_match = path_matcher.match(environ['PATH_INFO'])
|
| - if not path_match:
|
| - return _HTTP_NOT_FOUND(environ, start_response)
|
| - service_path = path_match.group(1)
|
| - method_name = path_match.group(2)
|
| -
|
| - content_type = environ.get('CONTENT_TYPE')
|
| - if not content_type:
|
| - content_type = environ.get('HTTP_CONTENT_TYPE')
|
| - if not content_type:
|
| - return _HTTP_BAD_REQUEST(environ, start_response)
|
| -
|
| - # TODO(rafek): Handle alternate encodings.
|
| - content_type = cgi.parse_header(content_type)[0]
|
| -
|
| - request_method = environ['REQUEST_METHOD']
|
| - if request_method != 'POST':
|
| - content = ('%s.%s is a ProtoRPC method.\n\n'
|
| - 'Service %s\n\n'
|
| - 'More about ProtoRPC: '
|
| - '%s\n' %
|
| - (service_path,
|
| - method_name,
|
| - service_class.definition_name().encode('utf-8'),
|
| - util.PROTORPC_PROJECT_URL))
|
| - error_handler = wsgi_util.error(
|
| - six.moves.http_client.METHOD_NOT_ALLOWED,
|
| - six.moves.http_client.responses[six.moves.http_client.METHOD_NOT_ALLOWED],
|
| - content=content,
|
| - content_type='text/plain; charset=utf-8')
|
| - return error_handler(environ, start_response)
|
| -
|
| - local_protocols = protocols or remote.Protocols.get_default()
|
| - try:
|
| - protocol = local_protocols.lookup_by_content_type(content_type)
|
| - except KeyError:
|
| - return _HTTP_UNSUPPORTED_MEDIA_TYPE(environ,start_response)
|
| -
|
| - def send_rpc_error(status_code, state, message, error_name=None):
|
| - """Helper function to send an RpcStatus message as response.
|
| -
|
| - Will create static error handler and begin response.
|
| -
|
| - Args:
|
| - status_code: HTTP integer status code.
|
| - state: remote.RpcState enum value to send as response.
|
| - message: Helpful message to send in response.
|
| - error_name: Error name if applicable.
|
| -
|
| - Returns:
|
| - List containing encoded content response using the same content-type as
|
| - the request.
|
| - """
|
| - status = remote.RpcStatus(state=state,
|
| - error_message=message,
|
| - error_name=error_name)
|
| - encoded_status = protocol.encode_message(status)
|
| - error_handler = wsgi_util.error(
|
| - status_code,
|
| - content_type=protocol.default_content_type,
|
| - content=encoded_status)
|
| - return error_handler(environ, start_response)
|
| -
|
| - method = remote_methods.get(method_name)
|
| - if not method:
|
| - return send_rpc_error(six.moves.http_client.BAD_REQUEST,
|
| - remote.RpcState.METHOD_NOT_FOUND_ERROR,
|
| - 'Unrecognized RPC method: %s' % method_name)
|
| -
|
| - content_length = int(environ.get('CONTENT_LENGTH') or '0')
|
| -
|
| - remote_info = method.remote
|
| - try:
|
| - request = protocol.decode_message(
|
| - remote_info.request_type, environ['wsgi.input'].read(content_length))
|
| - except (messages.ValidationError, messages.DecodeError) as err:
|
| - return send_rpc_error(six.moves.http_client.BAD_REQUEST,
|
| - remote.RpcState.REQUEST_ERROR,
|
| - 'Error parsing ProtoRPC request '
|
| - '(Unable to parse request content: %s)' % err)
|
| -
|
| - instance = service_factory()
|
| -
|
| - initialize_request_state = getattr(
|
| - instance, 'initialize_request_state', None)
|
| - if initialize_request_state:
|
| - # TODO(rafek): This is not currently covered by tests.
|
| - server_port = environ.get('SERVER_PORT', None)
|
| - if server_port:
|
| - server_port = int(server_port)
|
| -
|
| - headers = []
|
| - for name, value in six.iteritems(environ):
|
| - if name.startswith('HTTP_'):
|
| - headers.append((name[len('HTTP_'):].lower().replace('_', '-'), value))
|
| - request_state = remote.HttpRequestState(
|
| - remote_host=environ.get('REMOTE_HOST', None),
|
| - remote_address=environ.get('REMOTE_ADDR', None),
|
| - server_host=environ.get('SERVER_HOST', None),
|
| - server_port=server_port,
|
| - http_method=request_method,
|
| - service_path=service_path,
|
| - headers=headers)
|
| -
|
| - initialize_request_state(request_state)
|
| -
|
| - try:
|
| - response = method(instance, request)
|
| - encoded_response = protocol.encode_message(response)
|
| - except remote.ApplicationError as err:
|
| - return send_rpc_error(six.moves.http_client.BAD_REQUEST,
|
| - remote.RpcState.APPLICATION_ERROR,
|
| - err.message,
|
| - err.error_name)
|
| - except Exception as err:
|
| - logging.exception('Encountered unexpected error from ProtoRPC '
|
| - 'method implementation: %s (%s)' %
|
| - (err.__class__.__name__, err))
|
| - return send_rpc_error(six.moves.http_client.INTERNAL_SERVER_ERROR,
|
| - remote.RpcState.SERVER_ERROR,
|
| - 'Internal Server Error')
|
| -
|
| - response_headers = [('content-type', content_type)]
|
| - start_response('%d %s' % (six.moves.http_client.OK, six.moves.http_client.responses[six.moves.http_client.OK],),
|
| - response_headers)
|
| - return [encoded_response]
|
| -
|
| - # Return WSGI application.
|
| - return protorpc_service_app
|
| -
|
| -
|
| -@util.positional(1)
|
| -def service_mappings(services, registry_path=DEFAULT_REGISTRY_PATH):
|
| - """Create multiple service mappings with optional RegistryService.
|
| -
|
| - Use this function to create single WSGI application that maps to
|
| - multiple ProtoRPC services plus an optional RegistryService.
|
| -
|
| - Example:
|
| - services = service.service_mappings(
|
| - [(r'/time', TimeService),
|
| - (r'/weather', WeatherService)
|
| - ])
|
| -
|
| - In this example, the services WSGI application will map to two services,
|
| - TimeService and WeatherService to the '/time' and '/weather' paths
|
| - respectively. In addition, it will also add a ProtoRPC RegistryService
|
| - configured to serve information about both services at the (default) path
|
| - '/protorpc'.
|
| -
|
| - Args:
|
| - services: If a dictionary is provided instead of a list of tuples, the
|
| - dictionary item pairs are used as the mappings instead.
|
| - Otherwise, a list of tuples (service_path, service_factory):
|
| - service_path: The path to mount service on.
|
| - service_factory: A service class or service instance factory.
|
| - registry_path: A string to change where the registry is mapped (the default
|
| - location is '/protorpc'). When None, no registry is created or mounted.
|
| -
|
| - Returns:
|
| - WSGI application that serves ProtoRPC services on their respective URLs
|
| - plus optional RegistryService.
|
| - """
|
| - if isinstance(services, dict):
|
| - services = six.iteritems(services)
|
| -
|
| - final_mapping = []
|
| - paths = set()
|
| - registry_map = {} if registry_path else None
|
| -
|
| - for service_path, service_factory in services:
|
| - try:
|
| - service_class = service_factory.service_class
|
| - except AttributeError:
|
| - service_class = service_factory
|
| -
|
| - if service_path not in paths:
|
| - paths.add(service_path)
|
| - else:
|
| - raise remote.ServiceConfigurationError(
|
| - 'Path %r is already defined in service mapping' %
|
| - service_path.encode('utf-8'))
|
| -
|
| - if registry_map is not None:
|
| - registry_map[service_path] = service_class
|
| -
|
| - final_mapping.append(service_mapping(service_factory, service_path))
|
| -
|
| - if registry_map is not None:
|
| - final_mapping.append(service_mapping(
|
| - registry.RegistryService.new_factory(registry_map), registry_path))
|
| -
|
| - return wsgi_util.first_found(final_mapping)
|
| -
|
|
|