示例#1
0
 def testProcessingFault(self):
     """Tests whether we can handle a processing fault."""
     try:
         buf = SoapBuffer()
         buf.InjectXml(self.__class__.XML_RESPONSE_FAULT2)
         raise ApiError(buf.GetFaultAsDict())
     except ApiError, e:
         self.assertEqual(e.message, self.__class__.TRIGGER_MSG3)
示例#2
0
 def testErrorsFault(self):
     """Tests whether we can handle a fault with errors elements."""
     try:
         buf = SoapBuffer()
         buf.InjectXml(self.__class__.XML_RESPONSE_FAULT3)
         raise ApiError(buf.GetFaultAsDict())
     except ApiError, e:
         self.assertEqual(e.message, self.__class__.TRIGGER_MSG4)
         self.assertEqual(int(e.code), self.__class__.TRIGGER_CODE4)
示例#3
0
 def testStacktraceElement(self):
     """Tests whether we can handle a fault's stacktrace element."""
     try:
         buf = SoapBuffer()
         buf.InjectXml(self.__class__.XML_RESPONSE_FAULT1)
         raise ApiError(buf.GetFaultAsDict())
     except ApiError, e:
         self.assertEqual(e.message, self.__class__.TRIGGER_MSG2)
         self.assertEqual(int(e.code), self.__class__.TRIGGER_CODE2)
示例#4
0
    def testError502(self):
        """Test whether we can handle and report 502 errors."""
        # Temporarily redirect STDOUT into a buffer.
        buf = SoapBuffer()
        sys.stdout = buf

        html_code = Utils.ReadFile(os.path.join('data', 'http_error_502.html'))
        print html_code

        # Restore STDOUT.
        sys.stdout = sys.__stdout__

        if not buf.IsHandshakeComplete():
            data = buf.GetBufferAsStr()
        else:
            data = ''

        self.assertEqual(Utils.GetErrorFromHtml(data),
                         self.__class__.TRIGGER_MSG)
示例#5
0
 def testMalformedBuffer(self):
   """Tests whether we can handle a malformed SOAP buffer."""
   buf = SoapBuffer()
   buf.write('JUNK')
   self.assertRaises(MalformedBufferError, buf.GetCallResponseTime)
示例#6
0
  def CallRawMethod(self, soap_message):
    """Make an API call by posting raw SOAP XML message.

    Args:
      soap_message: str SOAP XML message.

    Returns:
      tuple response from the API method.
    """
    # Acquire thread lock.
    self.__lock.acquire()

    try:
      buf = SoapBuffer(
          xml_parser=self.__config['xml_parser'],
          pretty_xml=Utils.BoolTypeConvert(self.__config['use_pretty_xml']))
      http_header = {
          'post': '%s' % self.__url,
          'host': 'sandbox.google.com',
          'user_agent': '%s v%s; WebService.py' % (LIB_SHORT_NAME, LIB_VERSION),
          'content_type': 'text/xml; charset=\"UTF-8\"',
          'content_length': '%d' % len(soap_message),
          'soap_action': ''
      }

      version = self.__url.split('/')[-2]
      if SanityCheck.IsNewApi(version):
        http_header['host'] = 'adwords-%s' % http_header['host']

      index = self.__url.find('adwords.google.com')
      if index > -1:
        http_header['host'] = 'adwords.google.com'

      self.__url = ''.join(['https://', http_header['host'], self.__url])

      start_time = time.strftime('%Y-%m-%d %H:%M:%S')
      buf.write(
          ('%s Outgoing HTTP headers %s\nPOST %s\nHost: %s\nUser-Agent: '
           '%s\nContent-type: %s\nContent-length: %s\nSOAPAction: %s\n%s\n%s '
           'Outgoing SOAP %s\n%s\n%s\n' % ('*'*3, '*'*46, http_header['post'],
                                           http_header['host'],
                                           http_header['user_agent'],
                                           http_header['content_type'],
                                           http_header['content_length'],
                                           http_header['soap_action'], '*'*72,
                                           '*'*3, '*'*54, soap_message,
                                           '*'*72)))

      # Construct header and send SOAP message.
      web_service = httplib.HTTPS(http_header['host'])
      web_service.putrequest('POST', http_header['post'])
      web_service.putheader('Host', http_header['host'])
      web_service.putheader('User-Agent', http_header['user_agent'])
      web_service.putheader('Content-type', http_header['content_type'])
      web_service.putheader('Content-length', http_header['content_length'])
      web_service.putheader('SOAPAction', http_header['soap_action'])
      web_service.endheaders()
      web_service.send(soap_message)

      # Get response.
      status_code, status_message, header = web_service.getreply()
      response = web_service.getfile().read()

      header = str(header).replace('\r', '')
      buf.write(('%s Incoming HTTP headers %s\n%s %s\n%s\n%s\n%s Incoming SOAP'
                 ' %s\n%s\n%s\n' % ('*'*3, '*'*46, status_code, status_message,
                                    header, '*'*72, '*'*3, '*'*54, response,
                                    '*'*72)))
      stop_time = time.strftime('%Y-%m-%d %H:%M:%S')

      # Catch local errors prior to going down to the SOAP layer, which may not
      # exist for this error instance.
      if not buf.IsHandshakeComplete() or not buf.IsSoap():
        # The buffer contains non-XML data, most likely an HTML page. This
        # happens in the case of 502 errors.
        html_error = Utils.GetErrorFromHtml(buf.GetBufferAsStr())
        if html_error:
          msg = '%s' % html_error
        else:
          msg = 'Unknown error.'
        raise Error(msg)

      self.__ManageSoap(buf, start_time, stop_time,
                        {'data': buf.GetBufferAsStr()})
    finally:
      # Release thread lock.
      if self.__lock.locked():
        self.__lock.release()

    return (response,)
示例#7
0
  def CallMethod(self, method_name, params, service_name=None, loc=None,
                 request=None):
    """Make an API call to specified method.

    Args:
      method_name: str API method name.
      params: list list of parameters to send to the API method.
      [optional]
      service_name: str API service name.
      loc: service locator.
      request: instance holder of the SOAP request.

    Returns:
      tuple/str response from the API method. If 'raw_response' flag enabled a
                string is returned, tuple otherwise.
    """
    # Acquire thread lock.
    self.__lock.acquire()

    try:
      headers = self.__headers
      config = self.__config

      # Temporarily redirect HTTP headers and SOAP from STDOUT into a buffer.
      buf = SoapBuffer(
          xml_parser=config['xml_parser'],
          pretty_xml=Utils.BoolTypeConvert(config['use_pretty_xml']))
      old_stdout = sys.stdout
      sys.stdout = buf

      start_time = time.strftime('%Y-%m-%d %H:%M:%S')
      response = ()
      raw_response = ''
      error = {}
      try:
        if Utils.BoolTypeConvert(config['use_strict']):
          SanityCheck.ValidateHeadersForServer(headers,
                                               self.__op_config['server'])

        # Load/unload version specific authentication and configuration data.
        if SanityCheck.IsNewApi(self.__op_config['version']):
          # Set boolean to the format expected by the server, True => true.
          if 'validateOnly' in headers:
            headers['validateOnly'] = headers['validateOnly'].lower()

          # Load/set authentication token. If authentication token has expired,
          # regenerate it.
          now = time.time()
          if (Utils.BoolTypeConvert(config['use_auth_token']) and
              (('authToken' not in headers and
                'auth_token_epoch' not in config) or
               int(now - config['auth_token_epoch']) >= AUTH_TOKEN_EXPIRE)):
            if ('email' not in headers or not headers['email'] or
                'password' not in headers or not headers['password']):
              msg = ('Required authentication headers, \'email\' and '
                     '\'password\', are missing. Unable to regenerate '
                     'authentication token.')
              raise ValidationError(msg)
            headers['authToken'] = Utils.GetAuthToken(headers['email'],
                                                      headers['password'])
            config['auth_token_epoch'] = time.time()
            self.__headers = headers
            self.__config = config
          elif not Utils.BoolTypeConvert(config['use_auth_token']):
            msg = ('Requests via %s require use of authentication token.'
                   % self.__op_config['version'])
            raise ValidationError(msg)

          headers = Utils.UnLoadDictKeys(Utils.CleanUpDict(headers),
                                         ['email', 'password'])
          name_space = '/'.join(['https://adwords.google.com/api/adwords',
                                 self.__op_config['group'],
                                 self.__op_config['version']])
          config['ns_target'] = (name_space, 'RequestHeader')
        else:
          headers['useragent'] = headers['userAgent']
          headers = Utils.UnLoadDictKeys(headers, ['authToken', 'userAgent'])
          config = Utils.UnLoadDictKeys(config, ['ns_target',
                                                 'auth_token_epoch'])

        # Fire off API request and handle the response.
        if config['soap_lib'] == SOAPPY:
          from aw_api.soappy_toolkit import MessageHandler
          service = MessageHandler.GetServiceConnection(
              headers, config, self.__url, self.__op_config['http_proxy'],
              self.__op_config['version'])

          if not SanityCheck.IsNewApi(self.__op_config['version']):
            response = MessageHandler.UnpackResponseAsDict(
                service.invoke(method_name, params))
          else:
            response = MessageHandler.UnpackResponseAsDict(
                service._callWithBody(MessageHandler.SetRequestParams(
                    config, method_name, params)))
        elif config['soap_lib'] == ZSI:
          from aw_api.zsi_toolkit import MessageHandler
          service = MessageHandler.GetServiceConnection(
              headers, config, self.__url, self.__op_config['http_proxy'],
              service_name, loc)
          request = MessageHandler.SetRequestParams(self.__op_config, request,
                                                    params)

          response = MessageHandler.UnpackResponseAsTuple(
              eval('service.%s(request)' % method_name))

          # The response should always be tuple. If it's not, there must be
          # something wrong with MessageHandler.UnpackResponseAsTuple().
          if len(response) == 1 and isinstance(response[0], list):
            response = tuple(response[0])

        if isinstance(response, list):
          response = tuple(response)
        elif isinstance(response, tuple):
          pass
        else:
          if response:
            response = (response,)
          else:
            response = ()
      except Exception, e:
        error['data'] = e
      stop_time = time.strftime('%Y-%m-%d %H:%M:%S')

      # Restore STDOUT.
      sys.stdout = old_stdout

      # When debugging mode is ON, fetch last traceback.
      if Utils.BoolTypeConvert(self.__config['debug']):
        error['trace'] = Utils.LastStackTrace()

      # Catch local errors prior to going down to the SOAP layer, which may not
      # exist for this error instance.
      if 'data' in error and not buf.IsHandshakeComplete():
        # Check if buffer contains non-XML data, most likely an HTML page. This
        # happens in the case of 502 errors (and similar). Otherwise, this is a
        # local error and API request was never made.
        html_error = Utils.GetErrorFromHtml(buf.GetBufferAsStr())
        if html_error:
          msg = '%s' % html_error
        else:
          msg = str(error['data'])
          if Utils.BoolTypeConvert(self.__config['debug']):
            msg += '\n%s' % error['trace']

        # When debugging mode is ON, store the raw content of the buffer.
        if Utils.BoolTypeConvert(self.__config['debug']):
          error['raw_data'] = buf.GetBufferAsStr()

        # Catch errors from AuthToken and ValidationError levels, raised during
        # try/except above.
        if isinstance(error['data'], AuthTokenError):
          raise AuthTokenError(msg)
        elif isinstance(error['data'], ValidationError):
          raise ValidationError(error['data'])
        if 'raw_data' in error:
          msg = '%s [RAW DATA: %s]' % (msg, error['raw_data'])
        raise Error(msg)

      if Utils.BoolTypeConvert(self.__config['raw_response']):
        raw_response = buf.GetRawSOAPIn()

      self.__ManageSoap(buf, start_time, stop_time, error)
示例#8
0
 def testMalformedBuffer(self):
     """Tests whether we can handle a malformed SOAP buffer."""
     buf = SoapBuffer()
     buf.write('JUNK')
     self.assertRaises(MalformedBufferError, buf.GetCallResponseTime)