Search code examples
phpeclipseazurefiddler

PHP Azure Storage - on Table update I get: Server failed to authenticate the request


Hello mighty Windows Azure developers,

I am using PHP SDK for Windows Azure in eclipse working with storage table on local compute and storage emulator

I am running this code (basically I am updating data):

$statistics = AzureStorageTable::connection()->retrieveEntities(self::$statisticsTableName);
    foreach($statistics as $statistic) {
        $block = $statistic->getRowKey();
        if(isset($processedLogs[$block])) {
            $processedLog = $processedLogs[$block];
            $statistic->time    = ($statistic->time + $processedLog[0]);
            $statistic->count   = ($statistic->count + $processedLog[1]);
            $statistic->average = ($statistic->time / $statistic->count);
            AzureStorageTable::connection()->updateEntity(self::$statisticsTableName,$statistic);
        }           
    }

I get:

Microsoft_WindowsAzure_Exception

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

It fails here in the SDK:

Storage/Table.php (615) Microsoft_WindowsAzure_Storage_Table-> _changeEntity

The entity object looks like this:

Microsoft_WindowsAzure_Storage_DynamicTableEntity(5) ▼ {
   "_dynamicProperties" protected => array(4) ▼ {
      "timestamp" => stdClass(3) ▼ {
         "Name" => "Timestamp" (9)
         "Type" => "Edm.DateTime" (12)
         "Value" => DateTime(3) { ... }
      }
      "time" => stdClass(3) ▼ {
         "Name" => "time" (4)
         "Type" => "Edm.Double" (10)
         "Value" => 95.899748802185
      }
      "count" => stdClass(3) ▼ {
         "Name" => "count" (5)
         "Type" => "Edm.Int32" (9)
         "Value" => 44
      }
      "average" => stdClass(3) ▼ {
         "Name" => "average" (7)
         "Type" => "Edm.Double" (10)
         "Value" => 2.1795397455042
      }
   }
   "_partitionKey" protected => "timers" (6)
   "_rowKey" protected => "%2F" (3)
   "_timestamp" protected => DateTime(3) ▼ {
      "date" => "2012-04-20 22:51:50" (19)
      "timezone_type" => 3
      "timezone" => "UTC" (3)
   }
   "_etag" protected => "W/"datetime'2012-04-20T22%3A51%3A50.483Z'"" (42)
}

I had the same error also when trying to delete an entity.

I have tried to create the table entity instead of getting it from the storage and then using the same object for update but it doesn't work.

I know that there might be some issue with time according to googling but my time on my system is right (I am UTC+1). Somehow the time stamp in storage is 2 hours behind the actual time but I don't know what to do about it.

I do have Fiddler2 but I have no idea how to set it up to catch communication with http://127.0.0.1:10002 (local table storage).

Any idea what I am doing wrong please?


Solution

  • So... it is a bug in PHP Azure SDK from: http://phpazure.codeplex.com/

    I told the developers about it here: http://phpazure.codeplex.com/workitem/6901

    I am adding the solution here as well:

    The problem is that when I call this:

    $entity = $storage -> retrieveEntities($tableName);
    $entity -> Name = "New name;"
    $storage -> updateEntity($tableName,$entity);
    

    it fails giving me Microsoft_WindowsAzure_Exception Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

    The problem is that the result of retrieveEntities is *Microsoft_WindowsAzure_Storage_DynamicTableEntity* and then updateEntity calls on it getAzureValues and both *$this->_dynamicProperties* and parent::getAzureValues() return timestamp which leads to an array with two timestamps which leads to the error

    hot fix I made was adding this code:

    if(isset($this->_dynamicProperties["timestamp"]))unset($this->_dynamicProperties["timestamp"]);
    

    on the line before return in getAzureValues in *Microsoft_WindowsAzure_Storage_DynamicTableEntity*

    and then it works as a magic :]

    this error is both in the old SDK and in the latest SDK from trunk