$headers Lowercased names. * @param string|MultipartBody|null $body The body. * @throws ConnectionException When no answer came. */ public function send( string $method, string $url, array $headers, string|MultipartBody|null $body ): HttpResponse { $timeout = $this->timeout; if ( $body instanceof MultipartBody ) { if ( function_exists( 'curl_init' ) ) { return ( new CurlHttpClient( $this->upload_timeout ) )->send( $method, $url, $headers, $body ); } $length = $body->length(); if ( null === $length || $length > self::MAX_BUFFERED ) { throw new ConnectionException( __( 'This file is too large to upload without the PHP cURL extension.', 'vocalstack' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Shown as text. } $body = $body->contents(); $timeout = $this->upload_timeout; } $response = wp_remote_request( $url, array( 'method' => $method, 'headers' => $headers, 'body' => $body, 'timeout' => $timeout, 'redirection' => 0, 'user-agent' => 'VocalStack-WordPress/' . VOCALSTACK_VERSION . '; ' . home_url(), ) ); if ( is_wp_error( $response ) ) { throw new ConnectionException( $response->get_error_message() ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Shown as text. } $response_headers = wp_remote_retrieve_headers( $response ); return new HttpResponse( (int) wp_remote_retrieve_response_code( $response ), is_object( $response_headers ) && method_exists( $response_headers, 'getAll' ) ? $response_headers->getAll() : (array) $response_headers, (string) wp_remote_retrieve_body( $response ) ); } }