Example #1
0
  def request(self, operation, url, data=None, headers=None, 
      url_params=None):
    if isinstance(url, (str, unicode)):
      if url.startswith('http:') and self.ssl:
        # Force all requests to be https if self.ssl is True.
        url = atom_url.parse_url('https:' + url[5:])
      elif not url.startswith('http') and self.ssl: 
        url = atom_url.parse_url('https://%s%s' % (self.server, url))
      elif not url.startswith('http'):
        url = atom_url.parse_url('http://%s%s' % (self.server, url))
      else:
        url = atom_url.parse_url(url)

    if url_params:
      for name, value in url_params.iteritems():
        url.params[name] = value

    all_headers = self.additional_headers.copy()
    if headers:
      all_headers.update(headers)

    # If the list of headers does not include a Content-Length, attempt to
    # calculate it based on the data object.
    if data and 'Content-Length' not in all_headers:
      content_length = CalculateDataLength(data)
      if content_length:
        all_headers['Content-Length'] = str(content_length)

    # Find an Authorization token for this URL if one is available.
    if self.override_token:
      auth_token = self.override_token
    else:
      auth_token = self.token_store.find_token(url)
    return auth_token.perform_request(self.http_client, operation, url, 
        data=data, headers=all_headers)
Example #2
0
  def find_token(self, url):
    """Selects an Authorization header token which can be used for the URL.

    Args:
      url: str or atom_url.Url or a list containing the same.
          The URL which is going to be requested. All
          tokens are examined to see if any scopes begin match the beginning
          of the URL. The first match found is returned.

    Returns:
      The token object which should execute the HTTP request. If there was
      no token for the url (the url did not begin with any of the token
      scopes available), then the atom_http_interface.GenericToken will be 
      returned because the GenericToken calls through to the http client
      without adding an Authorization header.
    """
    if url is None:
      return None
    if isinstance(url, (str, unicode)):
      url = atom_url.parse_url(url)
    if url in self._tokens:
      token = self._tokens[url]
      if token.valid_for_scope(url):
        return token
      else:
        del self._tokens[url]
    for scope, token in self._tokens.iteritems():
      if token.valid_for_scope(url):
        return token
    return atom_http_interface.GenericToken()
Example #3
0
def ProcessUrl(service, url, for_proxy=False):
    """Processes a passed URL.  If the URL does not begin with https?, then
  the default value for server is used

  This method is deprecated, use atom_url.parse_url instead.
  """
    if not isinstance(url, atom_url.Url):
        url = atom_url.parse_url(url)

    server = url.host
    ssl = False
    port = 80

    if not server:
        if hasattr(service, 'server'):
            server = service.server
        else:
            server = service
        if not url.protocol and hasattr(service, 'ssl'):
            ssl = service.ssl
        if hasattr(service, 'port'):
            port = service.port
    else:
        if url.protocol == 'https':
            ssl = True
        elif url.protocol == 'http':
            ssl = False
        if url.port:
            port = int(url.port)
        elif port == 80 and ssl:
            port = 443

    return (server, port, ssl, url.get_request_uri())
Example #4
0
def ProcessUrl(service, url, for_proxy=False):
  """Processes a passed URL.  If the URL does not begin with https?, then
  the default value for server is used

  This method is deprecated, use atom_url.parse_url instead.
  """
  if not isinstance(url, atom_url.Url):
    url = atom_url.parse_url(url)

  server = url.host
  ssl = False
  port = 80

  if not server:
    if hasattr(service, 'server'):
      server = service.server
    else:
      server = service
    if not url.protocol and hasattr(service, 'ssl'):
      ssl = service.ssl
    if hasattr(service, 'port'):
      port = service.port
  else:
    if url.protocol == 'https':
      ssl = True
    elif url.protocol == 'http':
      ssl = False
    if url.port:
      port = int(url.port)
    elif port == 80 and ssl:
      port = 443

  return (server, port, ssl, url.get_request_uri())
Example #5
0
    def find_token(self, url):
        """Selects an Authorization header token which can be used for the URL.

    Args:
      url: str or atom_url.Url or a list containing the same.
          The URL which is going to be requested. All
          tokens are examined to see if any scopes begin match the beginning
          of the URL. The first match found is returned.

    Returns:
      The token object which should execute the HTTP request. If there was
      no token for the url (the url did not begin with any of the token
      scopes available), then the atom_http_interface.GenericToken will be 
      returned because the GenericToken calls through to the http client
      without adding an Authorization header.
    """
        if url is None:
            return None
        if isinstance(url, (str, unicode)):
            url = atom_url.parse_url(url)
        if url in self._tokens:
            token = self._tokens[url]
            if token.valid_for_scope(url):
                return token
            else:
                del self._tokens[url]
        for scope, token in self._tokens.iteritems():
            if token.valid_for_scope(url):
                return token
        return atom_http_interface.GenericToken()
Example #6
0
    def request(self,
                operation,
                url,
                data=None,
                headers=None,
                url_params=None):
        if isinstance(url, (str, unicode)):
            if url.startswith('http:') and self.ssl:
                # Force all requests to be https if self.ssl is True.
                url = atom_url.parse_url('https:' + url[5:])
            elif not url.startswith('http') and self.ssl:
                url = atom_url.parse_url('https://%s%s' % (self.server, url))
            elif not url.startswith('http'):
                url = atom_url.parse_url('http://%s%s' % (self.server, url))
            else:
                url = atom_url.parse_url(url)

        if url_params:
            for name, value in url_params.iteritems():
                url.params[name] = value

        all_headers = self.additional_headers.copy()
        if headers:
            all_headers.update(headers)

        # If the list of headers does not include a Content-Length, attempt to
        # calculate it based on the data object.
        if data and 'Content-Length' not in all_headers:
            content_length = CalculateDataLength(data)
            if content_length:
                all_headers['Content-Length'] = str(content_length)

        # Find an Authorization token for this URL if one is available.
        if self.override_token:
            auth_token = self.override_token
        else:
            auth_token = self.token_store.find_token(url)
        return auth_token.perform_request(self.http_client,
                                          operation,
                                          url,
                                          data=data,
                                          headers=all_headers)
Example #7
0
 def valid_for_scope(self, url):
     """Tells the caller if the token authorizes access to the desired URL.
 """
     if isinstance(url, (str, unicode)):
         url = atom_url.parse_url(url)
     for scope in self.scopes:
         if scope == atom_token_store.SCOPE_ALL:
             return True
         if isinstance(scope, (str, unicode)):
             scope = atom_url.parse_url(scope)
         if scope == url:
             return True
         # Check the host and the path, but ignore the port and protocol.
         elif scope.host == url.host and not scope.path:
             return True
         elif scope.host == url.host and scope.path and not url.path:
             continue
         elif scope.host == url.host and url.path.startswith(scope.path):
             return True
     return False
Example #8
0
 def valid_for_scope(self, url):
   """Tells the caller if the token authorizes access to the desired URL.
   """
   if isinstance(url, (str, unicode)):
     url = atom_url.parse_url(url)
   for scope in self.scopes:
     if scope == atom_token_store.SCOPE_ALL:
       return True
     if isinstance(scope, (str, unicode)):
       scope = atom_url.parse_url(scope)
     if scope == url:
       return True
     # Check the host and the path, but ignore the port and protocol.
     elif scope.host == url.host and not scope.path:
       return True
     elif scope.host == url.host and scope.path and not url.path:
       continue
     elif scope.host == url.host and url.path.startswith(scope.path):
       return True
   return False
Example #9
0
 def _prepare_connection(self, url, headers):
   if not isinstance(url, atom_url.Url):
     if isinstance(url, types.StringTypes):
       url = atom_url.parse_url(url)
     else:
       raise atom_http_interface.UnparsableUrlObject('Unable to parse url '
           'parameter because it was not a string or atom_url.Url')
   if url.protocol == 'https':
     if not url.port:
       return httplib.HTTPSConnection(url.host)
     return httplib.HTTPSConnection(url.host, int(url.port))
   else:
     if not url.port:
       return httplib.HTTPConnection(url.host)
     return httplib.HTTPConnection(url.host, int(url.port))
Example #10
0
 def _prepare_connection(self, url, headers):
     if not isinstance(url, atom_url.Url):
         if isinstance(url, types.StringTypes):
             url = atom_url.parse_url(url)
         else:
             raise atom_http_interface.UnparsableUrlObject(
                 'Unable to parse url '
                 'parameter because it was not a string or atom_url.Url')
     if url.protocol == 'https':
         if not url.port:
             return httplib.HTTPSConnection(url.host)
         return httplib.HTTPSConnection(url.host, int(url.port))
     else:
         if not url.port:
             return httplib.HTTPConnection(url.host)
         return httplib.HTTPConnection(url.host, int(url.port))
Example #11
0
  def request(self, operation, url, data=None, headers=None):
    """Performs an HTTP call to the server, supports GET, POST, PUT, and 
    DELETE.

    Usage example, perform and HTTP GET on http://www.google.com/:
      import atom.http
      client = atom.http.HttpClient()
      http_response = client.request('GET', 'http://www.google.com/')

    Args:
      operation: str The HTTP operation to be performed. This is usually one
          of 'GET', 'POST', 'PUT', or 'DELETE'
      data: filestream, list of parts, or other object which can be converted
          to a string. Should be set to None when performing a GET or DELETE.
          If data is a file-like object which can be read, this method will 
          read a chunk of 100K bytes at a time and send them. 
          If the data is a list of parts to be sent, each part will be 
          evaluated and sent.
      url: The full URL to which the request should be sent. Can be a string
          or atom_url.Url.
      headers: dict of strings. HTTP headers which should be sent
          in the request. 
    """
    all_headers = self.headers.copy()
    if headers:
      all_headers.update(headers)

    # If the list of headers does not include a Content-Length, attempt to
    # calculate it based on the data object.
    if data and 'Content-Length' not in all_headers:
      if isinstance(data, types.StringTypes):
        all_headers['Content-Length'] = str(len(data))
      else:
        raise atom_http_interface.ContentLengthRequired('Unable to calculate '
            'the length of the data parameter. Specify a value for '
            'Content-Length')

    # Set the content type to the default value if none was set.
    if 'Content-Type' not in all_headers:
      all_headers['Content-Type'] = DEFAULT_CONTENT_TYPE

    if self.v2_http_client is not None:
      http_request = atom_http_core.HttpRequest(method=operation)
      atom_http_core.Uri.parse_uri(str(url)).modify_request(http_request)
      http_request.headers = all_headers
      if data:
        http_request._body_parts.append(data)
      return self.v2_http_client.request(http_request=http_request)

    if not isinstance(url, atom_url.Url):
      if isinstance(url, types.StringTypes):
        url = atom_url.parse_url(url)
      else:
        raise atom_http_interface.UnparsableUrlObject('Unable to parse url '
            'parameter because it was not a string or atom_url.Url')
    
    connection = self._prepare_connection(url, all_headers)

    if self.debug:
      connection.debuglevel = 1

    connection.putrequest(operation, self._get_access_url(url), 
        skip_host=True)
    if url.port is not None:
      connection.putheader('Host', '%s:%s' % (url.host, url.port))
    else:
      connection.putheader('Host', url.host)

    # Overcome a bug in Python 2.4 and 2.5
    # httplib.HTTPConnection.putrequest adding
    # HTTP request header 'Host: www.google.com:443' instead of
    # 'Host: www.google.com', and thus resulting the error message
    # 'Token invalid - AuthSub token has wrong scope' in the HTTP response.
    if (url.protocol == 'https' and int(url.port or 443) == 443 and
        hasattr(connection, '_buffer') and
        isinstance(connection._buffer, list)):
      header_line = 'Host: %s:443' % url.host
      replacement_header_line = 'Host: %s' % url.host
      try:
        connection._buffer[connection._buffer.index(header_line)] = (
            replacement_header_line)
      except ValueError:  # header_line missing from connection._buffer
        pass

    # Send the HTTP headers.
    for header_name in all_headers:
      connection.putheader(header_name, all_headers[header_name])
    connection.endheaders()

    # If there is data, send it in the request.
    if data:
      if isinstance(data, list):
        for data_part in data:
          _send_data_part(data_part, connection)
      else:
        _send_data_part(data, connection)

    # Return the HTTP Response from the server.
    return connection.getresponse()
Example #12
0
    def request(self, operation, url, data=None, headers=None):
        """Performs an HTTP call to the server, supports GET, POST, PUT, and 
    DELETE.

    Usage example, perform and HTTP GET on http://www.google.com/:
      import atom.http
      client = atom.http.HttpClient()
      http_response = client.request('GET', 'http://www.google.com/')

    Args:
      operation: str The HTTP operation to be performed. This is usually one
          of 'GET', 'POST', 'PUT', or 'DELETE'
      data: filestream, list of parts, or other object which can be converted
          to a string. Should be set to None when performing a GET or DELETE.
          If data is a file-like object which can be read, this method will 
          read a chunk of 100K bytes at a time and send them. 
          If the data is a list of parts to be sent, each part will be 
          evaluated and sent.
      url: The full URL to which the request should be sent. Can be a string
          or atom_url.Url.
      headers: dict of strings. HTTP headers which should be sent
          in the request. 
    """
        all_headers = self.headers.copy()
        if headers:
            all_headers.update(headers)

        # If the list of headers does not include a Content-Length, attempt to
        # calculate it based on the data object.
        if data and 'Content-Length' not in all_headers:
            if isinstance(data, types.StringTypes):
                all_headers['Content-Length'] = str(len(data))
            else:
                raise atom_http_interface.ContentLengthRequired(
                    'Unable to calculate '
                    'the length of the data parameter. Specify a value for '
                    'Content-Length')

        # Set the content type to the default value if none was set.
        if 'Content-Type' not in all_headers:
            all_headers['Content-Type'] = DEFAULT_CONTENT_TYPE

        if self.v2_http_client is not None:
            http_request = atom_http_core.HttpRequest(method=operation)
            atom_http_core.Uri.parse_uri(str(url)).modify_request(http_request)
            http_request.headers = all_headers
            if data:
                http_request._body_parts.append(data)
            return self.v2_http_client.request(http_request=http_request)

        if not isinstance(url, atom_url.Url):
            if isinstance(url, types.StringTypes):
                url = atom_url.parse_url(url)
            else:
                raise atom_http_interface.UnparsableUrlObject(
                    'Unable to parse url '
                    'parameter because it was not a string or atom_url.Url')

        connection = self._prepare_connection(url, all_headers)

        if self.debug:
            connection.debuglevel = 1

        connection.putrequest(operation,
                              self._get_access_url(url),
                              skip_host=True)
        if url.port is not None:
            connection.putheader('Host', '%s:%s' % (url.host, url.port))
        else:
            connection.putheader('Host', url.host)

        # Overcome a bug in Python 2.4 and 2.5
        # httplib.HTTPConnection.putrequest adding
        # HTTP request header 'Host: www.google.com:443' instead of
        # 'Host: www.google.com', and thus resulting the error message
        # 'Token invalid - AuthSub token has wrong scope' in the HTTP response.
        if (url.protocol == 'https' and int(url.port or 443) == 443
                and hasattr(connection, '_buffer')
                and isinstance(connection._buffer, list)):
            header_line = 'Host: %s:443' % url.host
            replacement_header_line = 'Host: %s' % url.host
            try:
                connection._buffer[connection._buffer.index(header_line)] = (
                    replacement_header_line)
            except ValueError:  # header_line missing from connection._buffer
                pass

        # Send the HTTP headers.
        for header_name in all_headers:
            connection.putheader(header_name, all_headers[header_name])
        connection.endheaders()

        # If there is data, send it in the request.
        if data:
            if isinstance(data, list):
                for data_part in data:
                    _send_data_part(data_part, connection)
            else:
                _send_data_part(data, connection)

        # Return the HTTP Response from the server.
        return connection.getresponse()