Ejemplo n.º 1
0
    def testBuildRequest_DecodeError(self):
        """Test building a request generating a decode error."""
        expected_request = Request1()
        self.protocol.decode_message(Request1, 'my body').AndRaise(
            messages.DecodeError('xyz'))

        self.mox.ReplayAll()

        mapper = service_handlers.RPCMapper(['POST'], 'my-content-type',
                                            self.protocol)

        self.assertRaisesWithRegexpMatch(
            service_handlers.RequestError,
            'Unable to parse request content: xyz', mapper.build_request,
            self.handler, Request1)
Ejemplo n.º 2
0
    def decode_field(self, field, value):
        """Decode a JSON value to a python value.

    Args:
      field: A ProtoRPC field instance.
      value: A serialized JSON value.

    Returns:
      A Python value compatible with field.
    """

        if isinstance(field, messages.BytesField):
            try:
                return base64.urlsafe_b64decode(value)
            except TypeError, err:
                raise messages.DecodeError('Base64 decoding error: %s' % err)
Ejemplo n.º 3
0
    def decode_field(self, field, value):
        """Decode a JSON value to a python value.

    Args:
      field: A ProtoRPC field instance.
      value: A serialized JSON value.

    Returns:
      A Python value compatible with field.
    """

        if isinstance(field, messages.BytesField):
            try:

                padded_value = self.__pad_value(str(value), 4, '=')
                return base64.urlsafe_b64decode(padded_value)
            except (TypeError, UnicodeEncodeError) as err:
                raise messages.DecodeError('Base64 decoding error: %s' % err)

        return super(EndpointsProtoJson, self).decode_field(field, value)
Ejemplo n.º 4
0
    def decode_field(self, field, value):
        """Decode a JSON value to a python value.

    Args:
      field: A ProtoRPC field instance.
      value: A serialized JSON value.

    Returns:
      A Python value compatible with field.
    """
        # Override BytesField handling.  Client libraries typically use a url-safe
        # encoding.  b64decode doesn't handle these gracefully.  urlsafe_b64decode
        # handles both cases safely.  Also add padding if the padding is incorrect.
        if isinstance(field, messages.BytesField):
            try:
                # Need to call str(value) because ProtoRPC likes to pass values
                # as unicode, and urlsafe_b64decode can only handle bytes.
                padded_value = self.__pad_value(str(value), 4, '=')
                return base64.urlsafe_b64decode(padded_value)
            except (TypeError, UnicodeEncodeError), err:
                raise messages.DecodeError('Base64 decoding error: %s' % err)
Ejemplo n.º 5
0
 def build_request(handler, request):
   raise messages.DecodeError('This is a decode error')
Ejemplo n.º 6
0
  def add_parameter(self, parameter, values):
    """Add a single parameter.

    Adds a single parameter and its value to the request message.

    Args:
      parameter: Query string parameter to map to request.
      values: List of values to assign to request message.

    Returns:
      True if parameter was valid and added to the message, else False.

    Raises:
      DecodeError if the parameter refers to a valid field, and the values
      parameter does not have one and only one value.  Non-valid query
      parameters may have multiple values and should not cause an error.
    """
    path = self.make_path(parameter)

    if not path:
      return False

    # Must check that all indexes of all items in the path are correct before
    # instantiating any of them.  For example, consider:
    #
    #   class Repeated(object):
    #     ...
    #
    #   class Inner(object):
    #
    #     repeated = messages.MessageField(Repeated, 1, repeated=True)
    #
    #   class Outer(object):
    #
    #     inner = messages.MessageField(Inner, 1)
    #
    #   instance = Outer()
    #   builder = URLEncodedRequestBuilder(instance)
    #   builder.add_parameter('inner.repeated')
    #
    #   assert not hasattr(instance, 'inner')
    #
    # The check is done relative to the instance of Outer pass in to the
    # constructor of the builder.  This instance is not referred to at all
    # because all names are assumed to be relative to it.
    #
    # The 'repeated' part of the path is not correct because it is missing an
    # index.  Because it is missing an index, it should not create an instance
    # of Repeated.  In this case add_parameter will return False and have no
    # side effects.
    #
    # A correct path that would cause a new Inner instance to be inserted at
    # instance.inner and a new Repeated instance to be appended to the
    # instance.inner.repeated list would be 'inner.repeated-0'.
    if not self.__check_indexes(path):
      return False

    # Ok to build objects.
    parent_path = path[:-1]
    parent = self.__get_or_create_path(parent_path)
    name, index = path[-1]
    field = parent.field_by_name(name)

    if len(values) != 1:
      raise messages.DecodeError(
          'Found repeated values for field %s.' % field.name)

    value = values[0]

    if isinstance(field, messages.IntegerField):
      converted_value = int(value)
    elif isinstance(field, messages.MessageField):
      # Just make sure it's instantiated.  Assignment to field or
      # appending to list is done in __get_or_create_path.
      self.__get_or_create_path(path)
      return True
    elif isinstance(field, messages.StringField):
      converted_value = value.decode('utf-8')
    elif isinstance(field, messages.BooleanField):
      converted_value = value.lower() == 'true' and True or False
    else:
      converted_value = field.type(value)

    if field.repeated:
      value_list = getattr(parent, field.name, None)
      if value_list is None:
        setattr(parent, field.name, [converted_value])
      else:
        if index == len(value_list):
          value_list.append(converted_value)
        else:
          # Index should never be above len(value_list) because it was
          # verified during the index check above.
          value_list[index] = converted_value
    else:
      setattr(parent, field.name, converted_value)

    return True
Ejemplo n.º 7
0
def decode_message(message_type, encoded_message):
  """Decode protocol buffer to Message instance.

  Args:
    message_type: Message type to decode data to.
    encoded_message: Encoded version of message as string.

  Returns:
    Decoded instance of message_type.

  Raises:
    DecodeError if an error occurs during decoding, such as incompatible
      wire format for a field.
    messages.ValidationError if merged message is not initialized.
  """
  message = message_type()
  message_array = array.array('B')
  message_array.fromstring(encoded_message)
  try:
    decoder = _Decoder(message_array, 0, len(message_array))

    while decoder.avail() > 0:
      # Decode tag and variant information.
      encoded_tag = decoder.getVarInt32()
      tag = encoded_tag >> _WIRE_TYPE_BITS
      wire_type = encoded_tag & _WIRE_TYPE_MASK
      try:
        found_wire_type_decoder = _WIRE_TYPE_TO_DECODER_MAP[wire_type]
      except:
        raise messages.DecodeError('No such wire type %d' % wire_type)

      if tag < 1:
        raise messages.DecodeError('Invalid tag value %d' % tag)

      try:
        field = message.field_by_number(tag)
      except KeyError:
        # Unexpected tags are ok, just ignored unless below 0.
        field = None
        wire_type_decoder = found_wire_type_decoder
      else:
        expected_wire_type = _VARIANT_TO_WIRE_TYPE[field.variant]
        if expected_wire_type != wire_type:
          raise messages.DecodeError('Expected wire type %s but found %s' % (
              _WIRE_TYPE_NAME[expected_wire_type],
              _WIRE_TYPE_NAME[wire_type]))

        wire_type_decoder = _VARIANT_TO_DECODER_MAP[field.variant]

      value = wire_type_decoder(decoder)

      # Skip additional processing if unknown field.
      if not field:
        continue

      # Special case Enum and Message types.
      if isinstance(field, messages.EnumField):
        value = field.type(value)
      elif isinstance(field, messages.MessageField):
        nested_message = decode_message(field.type, value)
        value = nested_message

      # Merge value in to message.
      if field.repeated:
        values = getattr(message, field.name)
        if values is None:
          setattr(message, field.name, [value])
        else:
          values.append(value)
      else:
        setattr(message, field.name, value)
  except ProtocolBuffer.ProtocolBufferDecodeError, err:
    raise messages.DecodeError('Decoding error: %s' % str(err))