-
Notifications
You must be signed in to change notification settings - Fork 385
/
WpHttpRemoteGetRequest.php
157 lines (133 loc) · 3.85 KB
/
WpHttpRemoteGetRequest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php
/**
* Class WpHttpRemoteGetRequest.
*
* @package AmpProject\AmpWP
*/
namespace AmpProject\AmpWP\RemoteRequest;
use AmpProject\Exception\FailedToGetFromRemoteUrl;
use AmpProject\RemoteGetRequest;
use AmpProject\RemoteRequest\RemoteGetRequestResponse;
use AmpProject\Response;
use Traversable;
use WP_Error;
use WP_Http;
/**
* Remote request transport using the WordPress WP_Http abstraction layer.
*
* @package AmpProject\AmpWP
* @since 2.0
* @internal
*/
final class WpHttpRemoteGetRequest implements RemoteGetRequest {
/**
* Default timeout value to use in seconds.
*
* @var int
*/
const DEFAULT_TIMEOUT = 5;
/**
* Default number of retry attempts to do.
*
* @var int
*/
const DEFAULT_RETRIES = 2;
/**
* List of HTTP status codes that are worth retrying for.
*
* @var int[]
*/
const RETRYABLE_STATUS_CODES = [
WP_Http::REQUEST_TIMEOUT,
WP_Http::LOCKED,
WP_Http::TOO_MANY_REQUESTS,
WP_Http::INTERNAL_SERVER_ERROR,
WP_Http::SERVICE_UNAVAILABLE,
WP_Http::GATEWAY_TIMEOUT,
];
/**
* Whether to verify SSL certificates or not.
*
* @var boolean
*/
private $ssl_verify;
/**
* Timeout value to use in seconds.
*
* @var int
*/
private $timeout;
/**
* Number of retry attempts to do for an error that is worth retrying.
*
* @var int
*/
private $retries;
/**
* Instantiate a WpHttpRemoteGetRequest object.
*
* @param bool $ssl_verify Optional. Whether to verify SSL certificates. Defaults to true.
* @param int $timeout Optional. Timeout value to use in seconds. Defaults to 10.
* @param int $retries Optional. Number of retry attempts to do if a status code was thrown that is worth
* retrying. Defaults to 2.
*/
public function __construct( $ssl_verify = true, $timeout = self::DEFAULT_TIMEOUT, $retries = self::DEFAULT_RETRIES ) {
if ( ! is_int( $timeout ) || $timeout < 0 ) {
$timeout = self::DEFAULT_TIMEOUT;
}
if ( ! is_int( $retries ) || $retries < 0 ) {
$retries = self::DEFAULT_RETRIES;
}
$this->ssl_verify = $ssl_verify;
$this->timeout = $timeout;
$this->retries = $retries;
}
/**
* Do a GET request to retrieve the contents of a remote URL.
*
* @param string $url URL to get.
* @param array $headers Optional. Associative array of headers to send with the request. Defaults to empty array.
* @return Response Response for the executed request.
* @throws FailedToGetFromRemoteUrl If retrieving the contents from the URL failed.
*/
public function get( $url, $headers = [] ) {
$retries_left = $this->retries;
do {
$args = [
'method' => 'GET',
'timeout' => $this->timeout,
'sslverify' => $this->ssl_verify,
'headers' => $headers,
];
$response = wp_remote_get( $url, $args );
if ( $response instanceof WP_Error ) {
return new RemoteGetRequestResponse( $response->get_error_message(), [], 500 );
}
if ( empty( $response['response']['code'] ) ) {
return new RemoteGetRequestResponse(
! empty( $response['response']['message'] ) ? $response['response']['message'] : 'Unknown error',
[],
500
);
}
$status = $response['response']['code'];
if ( $status < 200 || $status >= 300 ) {
if ( ! $retries_left || in_array( $status, self::RETRYABLE_STATUS_CODES, true ) === false ) {
throw FailedToGetFromRemoteUrl::withHttpStatus( $url, $status );
}
continue;
}
$headers = $response['headers'];
if ( $headers instanceof Traversable ) {
$headers = iterator_to_array( $headers );
}
if ( ! is_array( $headers ) ) {
$headers = [];
}
return new RemoteGetRequestResponse( $response['body'], $headers, (int) $status );
} while ( $retries_left-- );
// This should never be triggered, but we want to ensure we always have a typed return value,
// to make PHPStan happy.
return new RemoteGetRequestResponse( '', [], 500 );
}
}