示例#1
0
def _update_entity(entity, if_match, encryption_required=False,
                   key_encryption_key=None, encryption_resolver=None):
    '''
    Constructs an update entity request.
    :param entity:
        The entity to insert. Could be a dict or an entity object.
    :param object key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)--wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()--returns the algorithm used to wrap the specified symmetric key.
        get_kid()--returns a string key id for this key-encryption-key.
    :param function(partition_key, row_key, property_name) encryption_resolver:
        A function that takes in an entities partition key, row key, and property name and returns
        a boolean that indicates whether that property should be encrypted.
    '''
    _validate_not_none('if_match', if_match)
    _validate_entity(entity, key_encryption_key is not None)
    _validate_encryption_required(encryption_required, key_encryption_key)

    request = HTTPRequest()
    request.method = 'PUT'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
        'If-Match': _to_str(if_match),
    }
    if key_encryption_key:
        entity = _encrypt_entity(entity, key_encryption_key, encryption_resolver)
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#2
0
def _insert_or_merge_entity(entity,
                            require_encryption=False,
                            key_encryption_key=None):
    '''
    Constructs an insert or merge entity request.
    :param entity:
        The entity to insert. Could be a dict or an entity object.
    :param object key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)--wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()--returns the algorithm used to wrap the specified symmetric key.
        get_kid()--returns a string key id for this key-encryption-key.
    '''
    _validate_entity(entity)
    _validate_encryption_unsupported(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'MERGE'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
    }
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#3
0
def _update_entity(entity,
                   if_match,
                   encryption_required=False,
                   key_encryption_key=None,
                   encryption_resolver=None):
    '''
    Constructs an update entity request.
    :param entity:
        The entity to insert. Could be a dict or an entity object.
    :param object key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)--wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()--returns the algorithm used to wrap the specified symmetric key.
        get_kid()--returns a string key id for this key-encryption-key.
    :param function(partition_key, row_key, property_name) encryption_resolver:
        A function that takes in an entities partition key, row key, and property name and returns
        a boolean that indicates whether that property should be encrypted.
    '''
    _validate_not_none('if_match', if_match)
    _validate_entity(entity, key_encryption_key is not None)
    _validate_encryption_required(encryption_required, key_encryption_key)

    request = HTTPRequest()
    request.method = 'PUT'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
        'If-Match': _to_str(if_match),
    }
    if key_encryption_key:
        entity = _encrypt_entity(entity, key_encryption_key,
                                 encryption_resolver)
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
    def _put_block_list(
            self, container_name, blob_name, block_list, content_settings=None,
            metadata=None, validate_content=False, lease_id=None, if_modified_since=None,
            if_unmodified_since=None, if_match=None, if_none_match=None,
            timeout=None, encryption_data=None):
        '''
        See put_block_list for more details. This helper method
        allows for encryption or other such special behavior because
        it is safely handled by the library. These behaviors are
        prohibited in the public version of this function.
        :param str encryption_data:
            A JSON formatted string containing the encryption metadata generated for this 
            blob if it was encrypted all at once upon upload. This should only be passed
            in by internal methods.
        '''

        _validate_not_none('container_name', container_name)
        _validate_not_none('blob_name', blob_name)
        _validate_not_none('block_list', block_list)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(container_name, blob_name)
        request.query = {
            'comp': 'blocklist',
            'timeout': _int_to_str(timeout),
        }
        request.headers = {
            'x-ms-lease-id': _to_str(lease_id),
            'If-Modified-Since': _datetime_to_utc_string(if_modified_since),
            'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since),
            'If-Match': _to_str(if_match),
            'If-None-Match': _to_str(if_none_match),
        }
        _add_metadata_headers(metadata, request)
        if content_settings is not None:
            request.headers.update(content_settings._to_headers())
        request.body = _get_request_body(
            _convert_block_list_to_xml(block_list))

        if validate_content:
            computed_md5 = _get_content_md5(request.body)
            request.headers['Content-MD5'] = _to_str(computed_md5)

        if encryption_data is not None:
            request.headers['x-ms-meta-encryptiondata'] = encryption_data

        return self._perform_request(request, _parse_base_properties)
示例#5
0
    def _put_block_list(
            self, container_name, blob_name, block_list, content_settings=None,
            metadata=None, validate_content=False, lease_id=None, if_modified_since=None,
            if_unmodified_since=None, if_match=None, if_none_match=None,
            timeout=None, encryption_data=None):
        '''
        See put_block_list for more details. This helper method
        allows for encryption or other such special behavior because
        it is safely handled by the library. These behaviors are
        prohibited in the public version of this function.
        :param str encryption_data:
            A JSON formatted string containing the encryption metadata generated for this 
            blob if it was encrypted all at once upon upload. This should only be passed
            in by internal methods.
        '''

        _validate_not_none('container_name', container_name)
        _validate_not_none('blob_name', blob_name)
        _validate_not_none('block_list', block_list)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(container_name, blob_name)
        request.query = {
            'comp': 'blocklist',
            'timeout': _int_to_str(timeout),
        }
        request.headers = {
            'x-ms-lease-id': _to_str(lease_id),
            'If-Modified-Since': _datetime_to_utc_string(if_modified_since),
            'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since),
            'If-Match': _to_str(if_match),
            'If-None-Match': _to_str(if_none_match),
        }
        _add_metadata_headers(metadata, request)
        if content_settings is not None:
            request.headers.update(content_settings._to_headers())
        request.body = _get_request_body(
            _convert_block_list_to_xml(block_list))

        if validate_content:
            computed_md5 = _get_content_md5(request.body)
            request.headers['Content-MD5'] = _to_str(computed_md5)

        if encryption_data is not None:
            request.headers['x-ms-meta-encryptiondata'] = encryption_data

        return self._perform_request(request, _parse_base_properties)
示例#6
0
def _merge_entity(entity, if_match, require_encryption=False, key_encryption_key=None):
    '''
    Constructs a merge entity request.
    '''
    _validate_not_none('if_match', if_match)
    _validate_entity(entity)
    _validate_encryption_unsupported(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'MERGE'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
        'If-Match': _to_str(if_match)
    }
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#7
0
    async def set_queue_service_properties(self,
                                           logging=None,
                                           hour_metrics=None,
                                           minute_metrics=None,
                                           cors=None,
                                           timeout=None):
        '''
        Sets the properties of a storage account's Queue service, including
        Azure Storage Analytics. If an element (ex Logging) is left as None, the 
        existing settings on the service for that functionality are preserved. 
        For more information on Azure Storage Analytics, see 
        https://msdn.microsoft.com/en-us/library/azure/hh343270.aspx.

        :param Logging logging:
            The logging settings provide request logs.
        :param Metrics hour_metrics:
            The hour metrics settings provide a summary of request 
            statistics grouped by API in hourly aggregates for queuess.
        :param Metrics minute_metrics:
            The minute metrics settings provide request statistics 
            for each minute for queues.
        :param cors:
            You can include up to five CorsRule elements in the 
            list. If an empty list is specified, all CORS rules will be deleted, 
            and CORS will be disabled for the service. For detailed information 
            about CORS rules and evaluation logic, see 
            https://msdn.microsoft.com/en-us/library/azure/dn535601.aspx.
        :type cors: list(:class:`~azure.storage.common.models.CorsRule`)
        :param int timeout:
            The server timeout, expressed in seconds.
        '''
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path()
        request.query = {
            'restype': 'service',
            'comp': 'properties',
            'timeout': _int_to_str(timeout),
        }
        request.body = _get_request_body(
            _convert_service_properties_to_xml(logging, hour_metrics,
                                               minute_metrics, cors))
        await self._perform_request(request)
示例#8
0
    async def set_queue_acl(self,
                            queue_name,
                            signed_identifiers=None,
                            timeout=None):
        '''
        Sets stored access policies for the queue that may be used with Shared 
        Access Signatures. 
        
        When you set permissions for a queue, the existing permissions are replaced. 
        To update the queue's permissions, call :func:`~get_queue_acl` to fetch 
        all access policies associated with the queue, modify the access policy 
        that you wish to change, and then call this function with the complete 
        set of data to perform the update.

        When you establish a stored access policy on a queue, it may take up to 
        30 seconds to take effect. During this interval, a shared access signature 
        that is associated with the stored access policy will throw an 
        :class:`AzureHttpError` until the access policy becomes active.

        :param str queue_name:
            The name of an existing queue.
        :param signed_identifiers:
            A dictionary of access policies to associate with the queue. The 
            dictionary may contain up to 5 elements. An empty dictionary 
            will clear the access policies set on the service. 
        :type signed_identifiers: dict(str, :class:`~azure.storage.common.models.AccessPolicy`)
        :param int timeout:
            The server timeout, expressed in seconds.
        '''
        _validate_not_none('queue_name', queue_name)
        _validate_access_policies(signed_identifiers)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(queue_name)
        self._set_basic_headers(request)
        request.query = {
            'comp': 'acl',
            'timeout': _int_to_str(timeout),
        }
        request.body = _get_request_body(
            _convert_signed_identifiers_to_xml(signed_identifiers))
        await self._perform_request(request)
示例#9
0
def _insert_or_replace_entity(entity, require_encryption=False,
                              key_encryption_key=None, encryption_resolver=None):
    '''
    Constructs an insert or replace entity request.
    '''
    _validate_entity(entity, key_encryption_key is not None)
    _validate_encryption_required(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'PUT'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
    }

    if key_encryption_key:
        entity = _encrypt_entity(entity, key_encryption_key, encryption_resolver)
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#10
0
def _merge_entity(entity,
                  if_match,
                  require_encryption=False,
                  key_encryption_key=None):
    '''
    Constructs a merge entity request.
    '''
    _validate_not_none('if_match', if_match)
    _validate_entity(entity)
    _validate_encryption_unsupported(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'MERGE'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
        'If-Match': _to_str(if_match)
    }
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
    def set_queue_service_properties(self, logging=None, hour_metrics=None,
                                     minute_metrics=None, cors=None, timeout=None):
        '''
        Sets the properties of a storage account's Queue service, including
        Azure Storage Analytics. If an element (ex Logging) is left as None, the 
        existing settings on the service for that functionality are preserved. 
        For more information on Azure Storage Analytics, see 
        https://msdn.microsoft.com/en-us/library/azure/hh343270.aspx.

        :param Logging logging:
            The logging settings provide request logs.
        :param Metrics hour_metrics:
            The hour metrics settings provide a summary of request 
            statistics grouped by API in hourly aggregates for queuess.
        :param Metrics minute_metrics:
            The minute metrics settings provide request statistics 
            for each minute for queues.
        :param cors:
            You can include up to five CorsRule elements in the 
            list. If an empty list is specified, all CORS rules will be deleted, 
            and CORS will be disabled for the service. For detailed information 
            about CORS rules and evaluation logic, see 
            https://msdn.microsoft.com/en-us/library/azure/dn535601.aspx.
        :type cors: list(:class:`~azure.storage.common.models.CorsRule`)
        :param int timeout:
            The server timeout, expressed in seconds.
        '''
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path()
        request.query = {
            'restype': 'service',
            'comp': 'properties',
            'timeout': _int_to_str(timeout),
        }
        request.body = _get_request_body(
            _convert_service_properties_to_xml(logging, hour_metrics, minute_metrics, cors))
        self._perform_request(request)
    def set_queue_acl(self, queue_name, signed_identifiers=None, timeout=None):
        '''
        Sets stored access policies for the queue that may be used with Shared 
        Access Signatures. 
        
        When you set permissions for a queue, the existing permissions are replaced. 
        To update the queue's permissions, call :func:`~get_queue_acl` to fetch 
        all access policies associated with the queue, modify the access policy 
        that you wish to change, and then call this function with the complete 
        set of data to perform the update.

        When you establish a stored access policy on a queue, it may take up to 
        30 seconds to take effect. During this interval, a shared access signature 
        that is associated with the stored access policy will throw an 
        :class:`AzureHttpError` until the access policy becomes active.

        :param str queue_name:
            The name of an existing queue.
        :param signed_identifiers:
            A dictionary of access policies to associate with the queue. The 
            dictionary may contain up to 5 elements. An empty dictionary 
            will clear the access policies set on the service. 
        :type signed_identifiers: dict(str, :class:`~azure.storage.common.models.AccessPolicy`)
        :param int timeout:
            The server timeout, expressed in seconds.
        '''
        _validate_not_none('queue_name', queue_name)
        _validate_access_policies(signed_identifiers)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(queue_name)
        request.query = {
            'comp': 'acl',
            'timeout': _int_to_str(timeout),
        }
        request.body = _get_request_body(
            _convert_signed_identifiers_to_xml(signed_identifiers))
        self._perform_request(request)
示例#13
0
def _insert_or_replace_entity(entity,
                              require_encryption=False,
                              key_encryption_key=None,
                              encryption_resolver=None):
    '''
    Constructs an insert or replace entity request.
    '''
    _validate_entity(entity, key_encryption_key is not None)
    _validate_encryption_required(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'PUT'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
    }

    if key_encryption_key:
        entity = _encrypt_entity(entity, key_encryption_key,
                                 encryption_resolver)
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#14
0
def _insert_or_merge_entity(entity, require_encryption=False, key_encryption_key=None):
    '''
    Constructs an insert or merge entity request.
    :param entity:
        The entity to insert. Could be a dict or an entity object.
    :param object key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)--wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()--returns the algorithm used to wrap the specified symmetric key.
        get_kid()--returns a string key id for this key-encryption-key.
    '''
    _validate_entity(entity)
    _validate_encryption_unsupported(require_encryption, key_encryption_key)

    request = HTTPRequest()
    request.method = 'MERGE'
    request.headers = {
        _DEFAULT_CONTENT_TYPE_HEADER[0]: _DEFAULT_CONTENT_TYPE_HEADER[1],
        _DEFAULT_ACCEPT_HEADER[0]: _DEFAULT_ACCEPT_HEADER[1],
    }
    request.body = _get_request_body(_convert_entity_to_json(entity))

    return request
示例#15
0
    async def update_message(self,
                             queue_name,
                             message_id,
                             pop_receipt,
                             visibility_timeout,
                             content=None,
                             timeout=None):
        '''
        Updates the visibility timeout of a message. You can also use this
        operation to update the contents of a message.

        This operation can be used to continually extend the invisibility of a 
        queue message. This functionality can be useful if you want a worker role 
        to "lease" a queue message. For example, if a worker role calls get_messages 
        and recognizes that it needs more time to process a message, it can 
        continually extend the message's invisibility until it is processed. If 
        the worker role were to fail during processing, eventually the message 
        would become visible again and another worker role could process it.

        If the key-encryption-key field is set on the local service object, this method will
        encrypt the content before uploading.

        :param str queue_name:
            The name of the queue containing the message to update.
        :param str message_id:
            The message id identifying the message to update.
        :param str pop_receipt:
            A valid pop receipt value returned from an earlier call
            to the :func:`~get_messages` or :func:`~update_message` operation.
        :param int visibility_timeout:
            Specifies the new visibility timeout value, in seconds,
            relative to server time. The new value must be larger than or equal
            to 0, and cannot be larger than 7 days. The visibility timeout of a
            message cannot be set to a value later than the expiry time. A
            message can be updated until it has been deleted or has expired.
        :param obj content:
            Message content. Allowed type is determined by the encode_function 
            set on the service. Default is str.
        :param int timeout:
            The server timeout, expressed in seconds.
        :return: 
            A list of :class:`~azure.storage.queue.models.QueueMessage` objects. For convenience,
            this object is also populated with the content, although it is not returned by the service.
        :rtype: list(:class:`~azure.storage.queue.models.QueueMessage`)
        '''

        _validate_encryption_required(self.require_encryption,
                                      self.key_encryption_key)

        _validate_not_none('queue_name', queue_name)
        _validate_not_none('message_id', message_id)
        _validate_not_none('pop_receipt', pop_receipt)
        _validate_not_none('visibility_timeout', visibility_timeout)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        self._set_basic_headers(request)
        request.path = _get_path(queue_name, True, message_id)
        request.query = {
            'popreceipt': _to_str(pop_receipt),
            'visibilitytimeout': _int_to_str(visibility_timeout),
            'timeout': _int_to_str(timeout)
        }

        if content is not None:
            request.body = _get_request_body(
                _convert_queue_message_xml(content, self.encode_function,
                                           self.key_encryption_key))

        return await self._perform_request(request,
                                           _parse_queue_message_from_headers)
示例#16
0
    async def put_message(self,
                          queue_name,
                          content,
                          visibility_timeout=None,
                          time_to_live=None,
                          timeout=None):
        '''
        Adds a new message to the back of the message queue. 

        The visibility timeout specifies the time that the message will be 
        invisible. After the timeout expires, the message will become visible. 
        If a visibility timeout is not specified, the default value of 0 is used.

        The message time-to-live specifies how long a message will remain in the 
        queue. The message will be deleted from the queue when the time-to-live 
        period expires.

        If the key-encryption-key field is set on the local service object, this method will
        encrypt the content before uploading.

        :param str queue_name:
            The name of the queue to put the message into.
        :param obj content:
            Message content. Allowed type is determined by the encode_function 
            set on the service. Default is str. The encoded message can be up to 
            64KB in size.
        :param int visibility_timeout:
            If not specified, the default value is 0. Specifies the
            new visibility timeout value, in seconds, relative to server time.
            The value must be larger than or equal to 0, and cannot be
            larger than 7 days. The visibility timeout of a message cannot be
            set to a value later than the expiry time. visibility_timeout
            should be set to a value smaller than the time-to-live value.
        :param int time_to_live:
            Specifies the time-to-live interval for the message, in
            seconds. The maximum time-to-live allowed is 7 days. If this
            parameter is omitted, the default time-to-live is 7 days.
        :param int timeout:
            The server timeout, expressed in seconds.
        :return:
            A :class:`~azure.storage.queue.models.QueueMessage` object.
            This object is also populated with the content although it is not
            returned from the service.
        :rtype: :class:`~azure.storage.queue.models.QueueMessage`
        '''

        _validate_encryption_required(self.require_encryption,
                                      self.key_encryption_key)

        _validate_not_none('queue_name', queue_name)
        _validate_not_none('content', content)
        request = HTTPRequest()
        request.method = 'POST'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(queue_name, True)
        self._set_basic_headers(request)
        request.query = {
            'visibilitytimeout': _to_str(visibility_timeout),
            'messagettl': _to_str(time_to_live),
            'timeout': _int_to_str(timeout)
        }

        request.body = _get_request_body(
            _convert_queue_message_xml(content, self.encode_function,
                                       self.key_encryption_key))

        message_list = await self._perform_request(
            request, _convert_xml_to_queue_messages,
            [self.decode_function, False, None, None, content])
        return message_list[0]
    def update_message(self, queue_name, message_id, pop_receipt, visibility_timeout,
                       content=None, timeout=None):
        '''
        Updates the visibility timeout of a message. You can also use this
        operation to update the contents of a message.

        This operation can be used to continually extend the invisibility of a 
        queue message. This functionality can be useful if you want a worker role 
        to "lease" a queue message. For example, if a worker role calls get_messages 
        and recognizes that it needs more time to process a message, it can 
        continually extend the message's invisibility until it is processed. If 
        the worker role were to fail during processing, eventually the message 
        would become visible again and another worker role could process it.

        If the key-encryption-key field is set on the local service object, this method will
        encrypt the content before uploading.

        :param str queue_name:
            The name of the queue containing the message to update.
        :param str message_id:
            The message id identifying the message to update.
        :param str pop_receipt:
            A valid pop receipt value returned from an earlier call
            to the :func:`~get_messages` or :func:`~update_message` operation.
        :param int visibility_timeout:
            Specifies the new visibility timeout value, in seconds,
            relative to server time. The new value must be larger than or equal
            to 0, and cannot be larger than 7 days. The visibility timeout of a
            message cannot be set to a value later than the expiry time. A
            message can be updated until it has been deleted or has expired.
        :param obj content:
            Message content. Allowed type is determined by the encode_function 
            set on the service. Default is str.
        :param int timeout:
            The server timeout, expressed in seconds.
        :return: 
            A list of :class:`~azure.storage.queue.models.QueueMessage` objects. For convenience,
            this object is also populated with the content, although it is not returned by the service.
        :rtype: list(:class:`~azure.storage.queue.models.QueueMessage`)
        '''

        _validate_encryption_required(self.require_encryption, self.key_encryption_key)

        _validate_not_none('queue_name', queue_name)
        _validate_not_none('message_id', message_id)
        _validate_not_none('pop_receipt', pop_receipt)
        _validate_not_none('visibility_timeout', visibility_timeout)
        request = HTTPRequest()
        request.method = 'PUT'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(queue_name, True, message_id)
        request.query = {
            'popreceipt': _to_str(pop_receipt),
            'visibilitytimeout': _int_to_str(visibility_timeout),
            'timeout': _int_to_str(timeout)
        }

        if content is not None:
            request.body = _get_request_body(_convert_queue_message_xml(content, self.encode_function,
                                                                        self.key_encryption_key))

        return self._perform_request(request, _parse_queue_message_from_headers)
    def put_message(self, queue_name, content, visibility_timeout=None,
                    time_to_live=None, timeout=None):
        '''
        Adds a new message to the back of the message queue. 

        The visibility timeout specifies the time that the message will be 
        invisible. After the timeout expires, the message will become visible. 
        If a visibility timeout is not specified, the default value of 0 is used.

        The message time-to-live specifies how long a message will remain in the 
        queue. The message will be deleted from the queue when the time-to-live 
        period expires.

        If the key-encryption-key field is set on the local service object, this method will
        encrypt the content before uploading.

        :param str queue_name:
            The name of the queue to put the message into.
        :param obj content:
            Message content. Allowed type is determined by the encode_function 
            set on the service. Default is str. The encoded message can be up to 
            64KB in size.
        :param int visibility_timeout:
            If not specified, the default value is 0. Specifies the
            new visibility timeout value, in seconds, relative to server time.
            The value must be larger than or equal to 0, and cannot be
            larger than 7 days. The visibility timeout of a message cannot be
            set to a value later than the expiry time. visibility_timeout
            should be set to a value smaller than the time-to-live value.
        :param int time_to_live:
            Specifies the time-to-live interval for the message, in
            seconds. The maximum time-to-live allowed is 7 days. If this
            parameter is omitted, the default time-to-live is 7 days.
        :param int timeout:
            The server timeout, expressed in seconds.
        :return:
            A :class:`~azure.storage.queue.models.QueueMessage` object.
            This object is also populated with the content although it is not
            returned from the service.
        :rtype: :class:`~azure.storage.queue.models.QueueMessage`
        '''

        _validate_encryption_required(self.require_encryption, self.key_encryption_key)

        _validate_not_none('queue_name', queue_name)
        _validate_not_none('content', content)
        request = HTTPRequest()
        request.method = 'POST'
        request.host_locations = self._get_host_locations()
        request.path = _get_path(queue_name, True)
        request.query = {
            'visibilitytimeout': _to_str(visibility_timeout),
            'messagettl': _to_str(time_to_live),
            'timeout': _int_to_str(timeout)
        }

        request.body = _get_request_body(_convert_queue_message_xml(content, self.encode_function,
                                                                    self.key_encryption_key))

        message_list = self._perform_request(request, _convert_xml_to_queue_messages,
                                             [self.decode_function, False,
                                              None, None, content])
        return message_list[0]