Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed recursion on payload too large #492

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Exception/PayloadTooLargeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Bugsnag\Exception;

class PayloadTooLargeException extends \RuntimeException {

private $payload;

public function __construct(array $payload) {
parent::__construct('Payload too large', 0, null);

$this->payload = $payload;
}

/**
* @return array
*/
public function getPayload() {
return $this->payload;
}


}
51 changes: 22 additions & 29 deletions src/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace Bugsnag;

use Bugsnag\Exception\PayloadTooLargeException;
use Exception;
use GuzzleHttp\ClientInterface;
use RuntimeException;

class HttpClient
{
class HttpClient {
/**
* The config instance.
*
Expand Down Expand Up @@ -46,13 +46,12 @@ class HttpClient
/**
* Create a new http client instance.
*
* @param \Bugsnag\Configuration $config the configuration instance
* @param \Bugsnag\Configuration $config the configuration instance
* @param \GuzzleHttp\ClientInterface $guzzle the guzzle client instance
*
* @return void
*/
public function __construct(Configuration $config, ClientInterface $guzzle)
{
public function __construct(Configuration $config, ClientInterface $guzzle) {
$this->config = $config;
$this->guzzle = $guzzle;
}
Expand All @@ -64,8 +63,7 @@ public function __construct(Configuration $config, ClientInterface $guzzle)
*
* @return void
*/
public function queue(Report $report)
{
public function queue(Report $report) {
$this->queue[] = $report;
}

Expand All @@ -78,8 +76,7 @@ public function queue(Report $report)
*
* @return void
*/
public function deploy(array $data)
{
public function deploy(array $data) {
$app = $this->config->getAppData();

$data['releaseStage'] = $app['releaseStage'];
Expand All @@ -100,8 +97,7 @@ public function deploy(array $data)
*
* @return void
*/
public function sendBuildReport(array $buildInfo)
{
public function sendBuildReport(array $buildInfo) {
$app = $this->config->getAppData();

$data = [];
Expand Down Expand Up @@ -157,8 +153,7 @@ public function sendBuildReport(array $buildInfo)
*
* @return void
*/
public function send()
{
public function send() {
if (!$this->queue) {
return;
}
Expand All @@ -173,8 +168,7 @@ public function send()
*
* @return array
*/
protected function build()
{
protected function build() {
$events = [];

foreach ($this->queue as $report) {
Expand All @@ -197,8 +191,7 @@ protected function build()
*
* @return array
*/
protected function getHeaders()
{
protected function getHeaders() {
return [
'Bugsnag-Api-Key' => $this->config->getApiKey(),
'Bugsnag-Sent-At' => strftime('%Y-%m-%dT%H:%M:%S'),
Expand All @@ -209,29 +202,31 @@ protected function getHeaders()
/**
* Post the given data to Bugsnag in json form.
*
* @param string $url the url to hit
* @param array $data the data send
* @param string $url the url to hit
* @param array $data the data send
*
* @return void
*/
protected function postJSON($url, $data)
{
protected function postJSON($url, $data) {
// Try to send the whole lot, or without the meta data for the first
// event. If failed, try to send the first event, and then the rest of
// them, recursively. Decrease by a constant and concquer if you like.
// Note that the base case is satisfied as soon as the payload is small
// enought to send, or when it's simply discarded.
try {
$normalized = $this->normalize($data);
} catch (PayloadTooLargeException $e) {
error_log('Bugsnag Warning: Couldn\'t notify, payload too large: ' . json_encode($e->getPayload()));
return;

} catch (RuntimeException $e) {
if (count($data['events']) > 1) {
$event = array_shift($data['events']);
$this->postJSON($url, array_merge($data, ['events' => [$event]]));
$this->postJSON($url, $data);
} else {
error_log('Bugsnag Warning: '.$e->getMessage());
error_log('Bugsnag Warning: ' . $e->getMessage());
}

return;
}

Expand All @@ -242,7 +237,7 @@ protected function postJSON($url, $data)
'headers' => $this->getHeaders(),
]);
} catch (Exception $e) {
error_log('Bugsnag Warning: Couldn\'t notify. '.$e->getMessage());
error_log('Bugsnag Warning: Couldn\'t notify. ' . $e->getMessage());
}
}

Expand All @@ -255,8 +250,7 @@ protected function postJSON($url, $data)
*
* @return array
*/
protected function normalize(array $data)
{
protected function normalize(array $data) {
$body = json_encode($data);

if ($this->length($body) > static::MAX_SIZE) {
Expand All @@ -266,7 +260,7 @@ protected function normalize(array $data)
$body = json_encode($data);

if ($this->length($body) > static::MAX_SIZE) {
throw new RuntimeException('Payload too large');
throw new PayloadTooLargeException($data);
}

return $data;
Expand All @@ -279,8 +273,7 @@ protected function normalize(array $data)
*
* @return int
*/
protected function length($str)
{
protected function length($str) {
return function_exists('mb_strlen') ? mb_strlen($str, '8bit') : strlen($str);
}
}