Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d5ace2b

Browse files
authoredMay 28, 2025··
Fix: Site-Health WebFinger check (#1733)
1 parent 170bab3 commit d5ace2b

File tree

4 files changed

+239
-7
lines changed

4 files changed

+239
-7
lines changed
 
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fixed
3+
4+
Fixed a bug in Site Health that caused a PHP warning and missing details for the WebFinger check.

‎includes/class-webfinger.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,17 +211,17 @@ public static function get_data( $uri ) {
211211
$webfinger_url = sprintf(
212212
'https://%s/.well-known/webfinger?resource=%s',
213213
$host,
214-
rawurlencode( $identifier )
214+
\rawurlencode( $identifier )
215215
);
216216

217-
$response = wp_safe_remote_get(
217+
$response = \wp_safe_remote_get(
218218
$webfinger_url,
219219
array(
220220
'headers' => array( 'Accept' => 'application/jrd+json' ),
221221
)
222222
);
223223

224-
if ( is_wp_error( $response ) ) {
224+
if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) >= 400 ) {
225225
return new WP_Error(
226226
'webfinger_url_not_accessible',
227227
__( 'The WebFinger Resource is not accessible.', 'activitypub' ),
@@ -232,8 +232,8 @@ public static function get_data( $uri ) {
232232
);
233233
}
234234

235-
$body = wp_remote_retrieve_body( $response );
236-
$data = json_decode( $body, true );
235+
$body = \wp_remote_retrieve_body( $response );
236+
$data = \json_decode( $body, true );
237237

238238
\set_transient( $transient_key, $data, WEEK_IN_SECONDS );
239239

‎includes/wp-admin/class-health-check.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,21 @@ public static function is_webfinger_endpoint_accessible() {
241241
$allowed
242242
);
243243

244+
$data = $url->get_error_data();
245+
$author_url = $resource;
246+
if ( isset( $data['data'] ) && \is_string( $data['data'] ) ) {
247+
$author_url = $data['data'];
248+
}
249+
244250
$health_messages = array(
245251
'webfinger_url_not_accessible' => \sprintf(
246252
$not_accessible,
247-
$url->get_error_data()['data']
253+
$author_url
248254
),
249255
'webfinger_url_invalid_response' => \sprintf(
250256
// translators: %s: Author URL.
251257
$invalid_response,
252-
$url->get_error_data()['data']
258+
$author_url
253259
),
254260
);
255261
$message = null;

‎tests/includes/class-test-webfinger.php

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,226 @@ public function the_cache_key_provider() {
4444
array( 'https://example.org', md5( 'https://example.org' ) ),
4545
);
4646
}
47+
48+
/**
49+
* Test the get_identifier_and_host method.
50+
*
51+
* @dataProvider the_identifier_and_host_provider
52+
* @covers ::get_identifier_and_host
53+
*
54+
* @param string $uri The URI to generate the identifier and host for.
55+
* @param string $identifier The expected identifier.
56+
* @param string $host The expected host.
57+
*/
58+
public function test_get_identifier_and_host( $uri, $identifier, $host ) {
59+
$this->assertEquals(
60+
array( $identifier, $host ),
61+
Webfinger::get_identifier_and_host( $uri )
62+
);
63+
}
64+
65+
/**
66+
* Identifier and host provider.
67+
*
68+
* @return array[]
69+
*/
70+
public function the_identifier_and_host_provider() {
71+
return array(
72+
array( 'author@example.org', 'acct:author@example.org', 'example.org' ),
73+
array( 'acct:author@example.org', 'acct:author@example.org', 'example.org' ),
74+
array( 'https://example.org/@pfefferle', 'https://example.org/@pfefferle', 'example.org' ),
75+
array( 'mailto:pfefferle@example.org', 'mailto:pfefferle@example.org', 'example.org' ),
76+
array( 'xmpp:pfefferle@example.com', 'xmpp:pfefferle@example.com', 'example.com' ),
77+
);
78+
}
79+
80+
/**
81+
* Test the get_data method.
82+
*
83+
* @dataProvider the_get_data_provider
84+
* @covers ::get_data
85+
*
86+
* @param string $uri The URI to get data for.
87+
* @param array $data The data to return.
88+
* @param array $expected The expected data.
89+
*/
90+
public function test_get_data( $uri, $data, $expected ) {
91+
$filter = function () use ( $data ) {
92+
return $data;
93+
};
94+
\add_filter( 'pre_http_request', $filter );
95+
96+
$data = Webfinger::get_data( $uri );
97+
98+
$this->assertEquals( $expected, $data );
99+
100+
\remove_filter( 'pre_http_request', $filter );
101+
}
102+
103+
/**
104+
* Data provider for test_get_data.
105+
*
106+
* @return array[]
107+
*/
108+
public function the_get_data_provider() {
109+
return array(
110+
array(
111+
'http://example.org/?author=1',
112+
array(
113+
'response' => array(
114+
'code' => 200,
115+
),
116+
'body' => '{ "subject": "acct:pfefferle@example.org", "aliases": [ "https://example.org/?author=1" ] }',
117+
),
118+
array(
119+
'subject' => 'acct:pfefferle@example.org',
120+
'aliases' => array( 'https://example.org/?author=1' ),
121+
),
122+
),
123+
array(
124+
'http://example.org/?author=1',
125+
array(
126+
'response' => array(
127+
'code' => 400,
128+
),
129+
'body' => 'error',
130+
),
131+
new \WP_Error(
132+
'webfinger_url_not_accessible',
133+
__( 'The WebFinger Resource is not accessible.', 'activitypub' ),
134+
array(
135+
'status' => 400,
136+
'data' => 'https://example.org/.well-known/webfinger?resource=http%3A%2F%2Fexample.org%2F%3Fauthor%3D1',
137+
)
138+
),
139+
),
140+
array(
141+
'test@example.org',
142+
array(
143+
'response' => array(
144+
'code' => 404,
145+
),
146+
'body' => '{"type":"about:blank","title":"activitypub_wrong_host","detail":"Der Ressourcen-Host stimmt nicht mit dem Blog-Host \u00fcberein","status":404,"metadata":{"code":"activitypub_wrong_host","message":"Der Ressourcen-Host stimmt nicht mit dem Blog-Host \u00fcberein","data":{"status":404}}}',
147+
),
148+
new \WP_Error(
149+
'webfinger_url_not_accessible',
150+
__( 'The WebFinger Resource is not accessible.', 'activitypub' ),
151+
array(
152+
'status' => 400,
153+
'data' => 'https://example.org/.well-known/webfinger?resource=acct%3Atest%40example.org',
154+
)
155+
),
156+
),
157+
);
158+
}
159+
160+
/**
161+
* Test the resolve method.
162+
*
163+
* @dataProvider the_resolve_provider
164+
* @covers ::resolve
165+
*
166+
* @param string $uri The URI to resolve.
167+
* @param array $data The data to return.
168+
* @param mixed $expected The expected result.
169+
*/
170+
public function test_resolve( $uri, $data, $expected ) {
171+
$filter = function () use ( $data ) {
172+
return $data;
173+
};
174+
\add_filter( 'pre_http_request', $filter );
175+
176+
$data = Webfinger::resolve( $uri );
177+
178+
$this->assertEquals( $expected, $data );
179+
180+
\remove_filter( 'pre_http_request', $filter );
181+
}
182+
183+
/**
184+
* Data provider for test_resolve.
185+
*
186+
* @return array[]
187+
*/
188+
public function the_resolve_provider() {
189+
return array(
190+
array(
191+
'http://example.org/?author=1',
192+
array(
193+
'response' => array(
194+
'code' => 200,
195+
),
196+
'body' => '{ "subject": "acct:test@example.org", "aliases": [ "https://example.org/?author=1" ] }',
197+
),
198+
new \WP_Error(
199+
'webfinger_missing_links',
200+
__( 'No valid Link elements found.', 'activitypub' ),
201+
array(
202+
'status' => 400,
203+
'data' => array(
204+
'subject' => 'acct:test@example.org',
205+
'aliases' => array( 'https://example.org/?author=1' ),
206+
),
207+
)
208+
),
209+
),
210+
array(
211+
'http://example.org/?author=1',
212+
array(
213+
'response' => array(
214+
'code' => 200,
215+
),
216+
'body' => '{ "subject": "acct:test@example.org", "aliases": [ "https://example.org/?author=1" ], "links": [] }',
217+
),
218+
new \WP_Error(
219+
'webfinger_missing_links',
220+
__( 'No valid Link elements found.', 'activitypub' ),
221+
array(
222+
'status' => 400,
223+
'data' => array(
224+
'subject' => 'acct:test@example.org',
225+
'aliases' => array( 'https://example.org/?author=1' ),
226+
'links' => array(),
227+
),
228+
)
229+
),
230+
),
231+
array(
232+
'http://example.org/?author=1',
233+
array(
234+
'response' => array(
235+
'code' => 200,
236+
),
237+
'body' => '{ "subject": "acct:test@example.org", "aliases": [ "https://example.org/?author=1" ], "links": [ { "rel": "http://webfinger.net/rel/profile-page", "href": "https://example.org/?author=1" } ] }',
238+
),
239+
new \WP_Error(
240+
'webfinger_url_no_activitypub',
241+
__( 'The Site supports WebFinger but not ActivityPub', 'activitypub' ),
242+
array(
243+
'status' => 400,
244+
'data' => array(
245+
'subject' => 'acct:test@example.org',
246+
'aliases' => array( 'https://example.org/?author=1' ),
247+
'links' => array(
248+
array(
249+
'rel' => 'http://webfinger.net/rel/profile-page',
250+
'href' => 'https://example.org/?author=1',
251+
),
252+
),
253+
),
254+
)
255+
),
256+
),
257+
array(
258+
'http://example.org/?author=1',
259+
array(
260+
'response' => array(
261+
'code' => 200,
262+
),
263+
'body' => '{ "subject": "acct:test@example.org", "aliases": [ "https://example.org/?author=1" ], "links": [ { "rel": "self", "type": "application/activity+json", "href": "https://example.org/?author=1" } ] }',
264+
),
265+
'https://example.org/?author=1',
266+
),
267+
);
268+
}
47269
}

0 commit comments

Comments
 (0)
Please sign in to comment.