strtoupper($type), 'timeout' => 10, 'headers' => [], ]; if (!empty($originHeader)) { // Domain-restricted resource keys: the cloud's allow-list check // reads Referer with priority over Origin (a browser sends both). // Send both so the key is recognised even behind a proxy that // forwards Referer but strips the Origin security header. $args['headers']['Origin'] = $originHeader; $args['headers']['Referer'] = $originHeader; } if ($content !== null && strcasecmp($type, 'POST') === 0) { $args['body'] = $content; } $response = wp_remote_request($url, $args); if (is_wp_error($response)) { throw new CloudRequestException( sprintf( "Transport error contacting cloud service at '%s': %s", $url, $response->get_error_message() ), 0, [] ); } $statusCode = (int) wp_remote_retrieve_response_code($response); $body = (string) wp_remote_retrieve_body($response); $headersObj = wp_remote_retrieve_headers($response); // Normalise WP's headers (Requests_Utility_CaseInsensitiveDictionary // or array) to the "Name: value" string list shape that // parseHeaders() / the upstream contract expect. $headerLines = []; $iterable = is_object($headersObj) && method_exists($headersObj, 'getAll') ? $headersObj->getAll() : (is_array($headersObj) ? $headersObj : []); foreach ($iterable as $k => $v) { $headerLines[] = $k . ': ' . (is_array($v) ? implode(', ', $v) : (string) $v); } // Mirror upstream HttpClient::validateResponse (it's private, so we // can't call it from a subclass — re-implement using the same // Constants for message parity). $message = null; if ($body !== '') { $json = json_decode($body, true); if (isset($json['errors']) && count($json['errors'])) { $message = implode(',', $json['errors']); } elseif ($statusCode !== 200) { $message = sprintf(Constants::MESSAGE_ERROR_CODE_RETURNED, $url, $statusCode, $body); } } else { $message = sprintf(Constants::MESSAGE_NO_DATA_IN_RESPONSE, $url); } if ($message !== null) { throw new CloudRequestException( sprintf(Constants::EXCEPTION_CLOUD_ERROR, $message), $statusCode, $this->parseHeaders($headerLines) ); } return $body; } }