Within the flow of HttpFetchException, the actual exception from curl is preserved and logged. Make HttpFetchException a pretty exception for when it is shown to users.
namespace BookStack\Exceptions;
-use Exception;
-
-class HttpFetchException extends Exception
+class HttpFetchException extends PrettyException
{
+ /**
+ * Construct exception within BookStack\Uploads\HttpFetcher.
+ */
+ public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+
+ if ($previous) {
+ $this->setDetails($previous->getMessage());
+ }
+ }
+
+ public function getStatusCode(): int
+ {
+ return 500;
+ }
}
curl_close($ch);
if ($err) {
- throw new HttpFetchException($err);
+ $errno = curl_errno($ch);
+ throw new HttpFetchException($err, $errno);
}
return $data;
$avatar = $this->saveAvatarImage($user);
$user->avatar()->associate($avatar);
$user->save();
- } catch (Exception $e) {
- Log::error('Failed to save user avatar image');
+ } catch (HttpFetchException $e) {
+ Log::error('Failed to save user avatar image', ['exception' => $e]);
}
}
$avatar = $this->createAvatarImageFromData($user, $imageData, $extension);
$user->avatar()->associate($avatar);
$user->save();
- } catch (Exception $e) {
- Log::error('Failed to save user avatar image');
+ } catch (HttpFetchException $e) {
+ Log::error('Failed to save user avatar image', ['exception' => $e]);
}
}
/**
* Gets an image from url and returns it as a string of image data.
*
- * @throws Exception
+ * @throws HttpFetchException
*/
protected function getAvatarImageData(string $url): string
{
try {
$imageData = $this->http->fetch($url);
} catch (HttpFetchException $exception) {
- throw new Exception(trans('errors.cannot_get_image_from_url', ['url' => $url]));
+ throw new HttpFetchException(trans('errors.cannot_get_image_from_url', ['url' => $url]), $exception->getCode(), $exception);
}
return $imageData;
use BookStack\Exceptions\HttpFetchException;
use BookStack\Uploads\HttpFetcher;
+use BookStack\Uploads\UserAvatars;
use BookStack\Users\Models\User;
use Tests\TestCase;
$this->createUserRequest($user);
$this->assertTrue($logger->hasError('Failed to save user avatar image'));
}
+
+ public function test_exception_message_on_failed_fetch()
+ {
+ // set wrong url
+ config()->set([
+ 'services.disable_services' => false,
+ 'services.avatar_url' => 'http_malformed_url/${email}/${hash}/${size}',
+ ]);
+
+ $user = User::factory()->make();
+ $avatar = app()->make(UserAvatars::class);
+ $url = 'http_malformed_url/' . urlencode(strtolower($user->email)) . '/' . md5(strtolower($user->email)) . '/500';
+ $logger = $this->withTestLogger();
+
+ $avatar->fetchAndAssignToUser($user);
+
+ $this->assertTrue($logger->hasError('Failed to save user avatar image'));
+ $exception = $logger->getRecords()[0]['context']['exception'];
+ $this->assertEquals(new HttpFetchException(
+ 'Cannot get image from ' . $url,
+ 6,
+ (new HttpFetchException('Could not resolve host: http_malformed_url', 6))
+ ), $exception);
+ }
}