Skip to content
This repository was archived by the owner on Oct 1, 2021. It is now read-only.

Commit 68d28ca

Browse files
authored
fix: handle case twitter url is invalid or twitter is down (#21)
1 parent f392e15 commit 68d28ca

File tree

4 files changed

+337
-12
lines changed

4 files changed

+337
-12
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"pestphp/pest-plugin-livewire": "^1.0.0",
3030
"phpunit/phpunit": "^9.5",
3131
"orchestra/testbench": "^6.2",
32-
"spatie/pest-plugin-snapshots": "^1.0"
32+
"spatie/pest-plugin-snapshots": "^1.0",
33+
"guzzlehttp/guzzle": "^7.3"
3334
},
3435
"autoload": {
3536
"psr-4": {

composer.lock

Lines changed: 212 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Extensions/Image/TwitterRenderer.php

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace ARKEcosystem\CommonMark\Extensions\Image;
44

5+
use Illuminate\Http\Client\ConnectionException;
6+
use Illuminate\Support\Arr;
57
use Illuminate\Support\Facades\Cache;
68
use Illuminate\Support\Facades\Http;
79

@@ -11,14 +13,33 @@ public static function render(MediaUrl $url)
1113
{
1214
$url = 'https://twitter.com/'.$url->getId();
1315

14-
return Cache::rememberForever(md5($url), fn () => Http::get('https://publish.twitter.com/oembed', [
15-
'url' => $url,
16-
'hide_thread' => 1,
17-
'hide_media' => 0,
18-
'omit_script' => true,
19-
'dnt' => true,
20-
'limit' => 20,
21-
'chrome' => 'nofooter',
22-
])->json()['html']);
16+
$result = Cache::rememberForever(md5($url), function () use ($url) {
17+
try {
18+
$response = Http::get('https://publish.twitter.com/oembed', [
19+
'url' => $url,
20+
'hide_thread' => 1,
21+
'hide_media' => 0,
22+
'omit_script' => true,
23+
'dnt' => true,
24+
'limit' => 20,
25+
'chrome' => 'nofooter',
26+
])->json();
27+
28+
return Arr::get($response, 'html', '');
29+
} catch (ConnectionException $e) {
30+
return false;
31+
}
32+
});
33+
34+
// If the result is `false`, means we had a connection error
35+
// (publish.twitter.com is down) in that case the results should not be
36+
// cached forever. We'll cache the result for 5 minutes.
37+
if ($result === false) {
38+
Cache::forget(md5($url));
39+
40+
return Cache::remember(md5($url), now()->addMinutes(5), fn () => '');
41+
}
42+
43+
return $result;
2344
}
2445
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
use ARKEcosystem\CommonMark\Extensions\Image\MediaUrl;
4+
use ARKEcosystem\CommonMark\Extensions\Image\TwitterRenderer;
5+
use Illuminate\Http\Client\ConnectionException;
6+
use Illuminate\Support\Carbon;
7+
use Illuminate\Support\Facades\Cache;
8+
use Illuminate\Support\Facades\Http;
9+
10+
it('should render twitter embeds', function () {
11+
$response = [
12+
'url' => 'https://twitter.com/arkecosystem/status/1234',
13+
'html' => '<blockquote>...</blockquote>',
14+
];
15+
16+
Http::fake([
17+
'publish.twitter.com/*' => $response,
18+
]);
19+
20+
$mediaUrl = new MediaUrl('twitter', 'arkecosystem/status/1234');
21+
$subject = new TwitterRenderer();
22+
23+
expect($subject->render($mediaUrl))->toBe('<blockquote>...</blockquote>');
24+
});
25+
26+
it('gets the response from the cache if set', function () {
27+
$id = 'arkecosystem/status/1234';
28+
Cache::set(md5('https://twitter.com/'.$id), '<blockquote>cached</blockquote>');
29+
30+
$mediaUrl = new MediaUrl('twitter', 'arkecosystem/status/1234');
31+
$subject = new TwitterRenderer();
32+
33+
expect($subject->render($mediaUrl))->toBe('<blockquote>cached</blockquote>');
34+
});
35+
36+
it('returns an empty string if receives an invalid response', function () {
37+
$response = [
38+
'invalid' => 'invalid',
39+
];
40+
41+
Http::fake([
42+
'publish.twitter.com/*' => $response,
43+
]);
44+
45+
$mediaUrl = new MediaUrl('twitter', 'arkecosystem/status/1234');
46+
47+
$subject = new TwitterRenderer();
48+
49+
expect($subject->render($mediaUrl))->toBe('');
50+
});
51+
52+
it('returns an empty string if twitter server is down', function () {
53+
Http::fake([
54+
'publish.twitter.com/*' => function () {
55+
throw new ConnectionException();
56+
},
57+
]);
58+
59+
$mediaUrl = new MediaUrl('twitter', 'arkecosystem/status/1234');
60+
61+
$subject = new TwitterRenderer();
62+
63+
expect($subject->render($mediaUrl))->toBe('');
64+
});
65+
66+
it('caches the response for 5 minutes if server is down', function () {
67+
$id = 'arkecosystem/status/1234';
68+
$cacheKey = md5('https://twitter.com/'.$id);
69+
70+
Cache::shouldReceive('rememberForever')
71+
->once()
72+
->with($cacheKey, \Closure::class)
73+
->andReturn(false)
74+
->shouldReceive('forget')
75+
->once()
76+
->with($cacheKey)
77+
->shouldReceive('remember')
78+
->with($cacheKey, Carbon::class, \Closure::class)
79+
->once()
80+
->andReturn('');
81+
82+
Http::fake([
83+
'publish.twitter.com/*' => function () {
84+
throw new ConnectionException();
85+
},
86+
]);
87+
88+
$mediaUrl = new MediaUrl('twitter', $id);
89+
90+
$subject = new TwitterRenderer();
91+
92+
expect($subject->render($mediaUrl))->toBe('');
93+
});

0 commit comments

Comments
 (0)