phpazurehttpsazure-servicebus-queueshttp-request2

PHP Azure SDK Service Bus returns Malformed Response


I'm working on trace logger of sorts that pushes log message requests onto a Queue on a Service Bus, to later be picked off by a worker role which would insert them into the table store. While running on my machine, this works just fine (since I'm the only one using it), but once I put it up on a server to test, it produced the following error:

HTTP_Request2_MessageException: Malformed response: in D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php on line 1013
0   HTTP_Request2_Response->__construct('', true, Object(Net_URL2)) D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:1013
1   HTTP_Request2_Adapter_Socket->readResponse()    D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:139
2   HTTP_Request2_Adapter_Socket->sendRequest(Object(HTTP_Request2))    D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2.php:939
3   HTTP_Request2->send()   D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\Http\HttpClient.php:262
4   WindowsAzure\Common\Internal\Http\HttpClient->send(Array, Object(WindowsAzure\Common\Internal\Http\Url))    D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\RestProxy.php:141
5   WindowsAzure\Common\Internal\RestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext))  D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\ServiceRestProxy.php:86
6   WindowsAzure\Common\Internal\ServiceRestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext))   D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:139
7   WindowsAzure\ServiceBus\ServiceBusRestProxy->sendMessage('<queuename>/mes…', Object(WindowsAzure\ServiceBus\Models\BrokeredMessage))    D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:155
⋮

I've seen previous posts that describe similar issues; Namely:

That imply that this is a known issue regarding the PHP Azure Storage libraries, where there are a limited amount of HTTPS connections allowed. Before requirements were changed, I was accessing the table store directly, and ran into this same issue, and fixed it in the way the first link describes.

The problem is that the Service Bus endpoint in the connection string, unlike Table Store (etc.) connection string endpoints, MUST be 'HTTPS'. Trying to use it with 'HTTP' will return a 400 - Bad Request error.

I was wondering if anyone had any ideas on a potential workaround. Any advice would be greatly appreciated.

Thanks!

EDIT (After Gary Liu's Comment):

Here's the code I use to add items to the queue:

private function logToAzureSB($source, $msg, $severity, $machine)
{
    // Gather all relevant information
    $msgInfo = array(
        "Severity" => $severity,
        "Message" => $msg,
        "Machine" => $machine,
        "Source" => $source
        );
    // Encode it to a JSON string, and add it to a Brokered message.
    $encoded = json_encode($msgInfo);
    $message = new BrokeredMessage($encoded);
    $message->setContentType("application/json");
    // Attempt to push the message onto the Queue
    try
    {
        $this->sbRestProxy->sendQueueMessage($this->azureQueueName, $message);
    }
    catch(ServiceException $e)
    {
        throw new \DatabaseException($e->getMessage, $e->getCode, $e->getPrevious);
    }
}

Here, $this->sbRestProxy is a Service Bus REST Proxy, set up when the logging class initializes.

On the recieving end of things, here's the code on the Worker role side of this:

public override void Run()
{
     // Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump.
     Client.OnMessage((receivedMessage) =>
     {
         try
         {
             // Pull the Message from the recieved object.
             Stream stream = receivedMessage.GetBody<Stream>();
             StreamReader reader = new StreamReader(stream);
             string message = reader.ReadToEnd();
             LoggingMessage mMsg = JsonConvert.DeserializeObject<LoggingMessage>(message);

              // Create an entry with the information given.
              LogEntry entry = new LogEntry(mMsg);

              // Set the Logger to the appropriate table store, and insert the entry into the table.
              Logger.InsertIntoLog(entry, mMsg.Service);
          }
          catch
          {
              // Handle any message processing specific exceptions here
          }
      });

      CompletedEvent.WaitOne();
}

Where Logging Message is a simple object that basically contains the same fields as the Message Logged in PHP (Used for JSON Deserialization), LogEntry is a TableEntity which contains these fields as well, and Logger is an instance of a Table Store Logger, set up during the worker role's OnStart method.


Solution

  • This was a known issue with the Windows Azure PHP, which hasn't been looked at in a long time, nor has it been fixed. In the time between when I posted this and now, We ended up writing a separate API web service for logging, and had our PHP Code send JSON strings to it over cURL, which works well enough as a temporary work around. We're moving off of PHP now, so this wont be an issue for much longer anyways.