Skip to content

Commit

Permalink
Merge pull request #57 from brianjmiller/issue38-exceptions-rebased
Browse files Browse the repository at this point in the history
Protect RemoteLRS from exceptions in sendRequest
  • Loading branch information
brianjmiller committed Mar 30, 2016
2 parents 3f8e1e0 + d634afb commit 3aa6057
Showing 1 changed file with 53 additions and 30 deletions.
83 changes: 53 additions & 30 deletions src/RemoteLRS.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,42 +117,65 @@ protected function sendRequest($method, $resource) {
}
}

$context = stream_context_create(array( 'http' => $http ));
$fp = fopen($url, 'rb', false, $context);
if (! $fp) {
throw new \Exception("Request failed: $php_errormsg");
}

$metadata = stream_get_meta_data($fp);
$content = stream_get_contents($fp);

$response = $this->_parseMetadata($metadata, $options);
$success = false;

//
// keep a copy of the raw content, the methods expecting
// an LRS response may handle the content, for instance
// querying statements takes the returned value and converts
// it to Statement objects (really StatementsResult but who
// is counting), etc. but a user may want the original raw
// returned content untouched, do the same with the metadata
// because it feels like a good practice
// errors from fopen are reported to PHP as E_WARNING which prevents us
// from getting a reasonable message, so set an error handler here for
// the immediate call to turn it into an exception, and then restore
// normal handling
//
$response['_content'] = $content;
$response['_metadata'] = $metadata;
set_error_handler(
function ($errno, $errstr, $errfile, $errline, array $errcontext) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
);

//
// Content-Type won't be set in the case of a 204 (and potentially others)
//
if (isset($response['headers']['contentType']) && $response['headers']['contentType'] === "multipart/mixed") {
$content = $this->_parseMultipart($response['headers']['contentTypeBoundary'], $content);
}
try {
$context = stream_context_create(array( 'http' => $http ));
$fp = fopen($url, 'rb', false, $context);

$success = false;
if (($response['status'] >= 200 && $response['status'] < 300) || ($response['status'] === 404 && isset($options['ignore404']) && $options['ignore404'])) {
$success = true;
if (! $fp) {
$content = "Request failed: $php_errormsg";
}
}
catch (ErrorException $ex) {
$content = "Request failed: $ex";
}
elseif ($response['status'] >= 300 && $response['status'] < 400) {
throw new \Exception("Unsupported status code: " . $response['status'] . " (LRS should not redirect)");

restore_error_handler();

if ($fp) {
$metadata = stream_get_meta_data($fp);
$content = stream_get_contents($fp);

$response = $this->_parseMetadata($metadata, $options);

//
// keep a copy of the raw content, the methods expecting
// an LRS response may handle the content, for instance
// querying statements takes the returned value and converts
// it to Statement objects (really StatementsResult but who
// is counting), etc. but a user may want the original raw
// returned content untouched, do the same with the metadata
// because it feels like a good practice
//
$response['_content'] = $content;
$response['_metadata'] = $metadata;

//
// Content-Type won't be set in the case of a 204 (and potentially others)
//
if (isset($response['headers']['contentType']) && $response['headers']['contentType'] === "multipart/mixed") {
$content = $this->_parseMultipart($response['headers']['contentTypeBoundary'], $content);
}

if (($response['status'] >= 200 && $response['status'] < 300) || ($response['status'] === 404 && isset($options['ignore404']) && $options['ignore404'])) {
$success = true;
}
elseif ($response['status'] >= 300 && $response['status'] < 400) {
$content = "Unsupported status code: " . $response['status'] . " (LRS should not redirect)";
}
}

return new LRSResponse($success, $content, $response);
Expand Down

0 comments on commit 3aa6057

Please sign in to comment.