Skip to content

Commit 3aa6057

Browse files
committed
Merge pull request #57 from brianjmiller/issue38-exceptions-rebased
Protect RemoteLRS from exceptions in sendRequest
2 parents 3f8e1e0 + d634afb commit 3aa6057

1 file changed

Lines changed: 53 additions & 30 deletions

File tree

src/RemoteLRS.php

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -117,42 +117,65 @@ protected function sendRequest($method, $resource) {
117117
}
118118
}
119119

120-
$context = stream_context_create(array( 'http' => $http ));
121-
$fp = fopen($url, 'rb', false, $context);
122-
if (! $fp) {
123-
throw new \Exception("Request failed: $php_errormsg");
124-
}
125-
126-
$metadata = stream_get_meta_data($fp);
127-
$content = stream_get_contents($fp);
128-
129-
$response = $this->_parseMetadata($metadata, $options);
120+
$success = false;
130121

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

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

150-
$success = false;
151-
if (($response['status'] >= 200 && $response['status'] < 300) || ($response['status'] === 404 && isset($options['ignore404']) && $options['ignore404'])) {
152-
$success = true;
138+
if (! $fp) {
139+
$content = "Request failed: $php_errormsg";
140+
}
141+
}
142+
catch (ErrorException $ex) {
143+
$content = "Request failed: $ex";
153144
}
154-
elseif ($response['status'] >= 300 && $response['status'] < 400) {
155-
throw new \Exception("Unsupported status code: " . $response['status'] . " (LRS should not redirect)");
145+
146+
restore_error_handler();
147+
148+
if ($fp) {
149+
$metadata = stream_get_meta_data($fp);
150+
$content = stream_get_contents($fp);
151+
152+
$response = $this->_parseMetadata($metadata, $options);
153+
154+
//
155+
// keep a copy of the raw content, the methods expecting
156+
// an LRS response may handle the content, for instance
157+
// querying statements takes the returned value and converts
158+
// it to Statement objects (really StatementsResult but who
159+
// is counting), etc. but a user may want the original raw
160+
// returned content untouched, do the same with the metadata
161+
// because it feels like a good practice
162+
//
163+
$response['_content'] = $content;
164+
$response['_metadata'] = $metadata;
165+
166+
//
167+
// Content-Type won't be set in the case of a 204 (and potentially others)
168+
//
169+
if (isset($response['headers']['contentType']) && $response['headers']['contentType'] === "multipart/mixed") {
170+
$content = $this->_parseMultipart($response['headers']['contentTypeBoundary'], $content);
171+
}
172+
173+
if (($response['status'] >= 200 && $response['status'] < 300) || ($response['status'] === 404 && isset($options['ignore404']) && $options['ignore404'])) {
174+
$success = true;
175+
}
176+
elseif ($response['status'] >= 300 && $response['status'] < 400) {
177+
$content = "Unsupported status code: " . $response['status'] . " (LRS should not redirect)";
178+
}
156179
}
157180

158181
return new LRSResponse($success, $content, $response);

0 commit comments

Comments
 (0)