[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ai-client/adapters/ -> class-wp-ai-client-http-client.php (source)

   1  <?php
   2  /**
   3   * WP AI Client: WP_AI_Client_HTTP_Client class
   4   *
   5   * @package WordPress
   6   * @subpackage AI
   7   * @since 7.0.0
   8   */
   9  
  10  use WordPress\AiClientDependencies\Psr\Http\Client\ClientInterface;
  11  use WordPress\AiClientDependencies\Psr\Http\Message\RequestInterface;
  12  use WordPress\AiClientDependencies\Psr\Http\Message\ResponseInterface;
  13  use WordPress\AiClientDependencies\Psr\Http\Message\ResponseFactoryInterface;
  14  use WordPress\AiClientDependencies\Psr\Http\Message\StreamFactoryInterface;
  15  use WordPress\AiClient\Providers\Http\Contracts\ClientWithOptionsInterface;
  16  use WordPress\AiClient\Providers\Http\DTO\RequestOptions;
  17  use WordPress\AiClient\Providers\Http\Exception\NetworkException;
  18  
  19  /**
  20   * PSR-18 HTTP Client adapter using WordPress HTTP API.
  21   *
  22   * Allows WordPress HTTP functions to be used as a PSR-18 compliant HTTP client
  23   * for the AI Client SDK.
  24   *
  25   * @since 7.0.0
  26   * @internal Intended only to wire up the PHP AI Client SDK to WordPress's HTTP client.
  27   * @access private
  28   */
  29  class WP_AI_Client_HTTP_Client implements ClientInterface, ClientWithOptionsInterface {
  30  
  31      /**
  32       * Response factory instance.
  33       *
  34       * @since 7.0.0
  35       */
  36      private ResponseFactoryInterface $response_factory;
  37  
  38      /**
  39       * Stream factory instance.
  40       *
  41       * @since 7.0.0
  42       */
  43      private StreamFactoryInterface $stream_factory;
  44  
  45      /**
  46       * Constructor.
  47       *
  48       * @since 7.0.0
  49       *
  50       * @param ResponseFactoryInterface $response_factory PSR-17 Response factory.
  51       * @param StreamFactoryInterface   $stream_factory   PSR-17 Stream factory.
  52       */
  53  	public function __construct( ResponseFactoryInterface $response_factory, StreamFactoryInterface $stream_factory ) {
  54          $this->response_factory = $response_factory;
  55          $this->stream_factory   = $stream_factory;
  56      }
  57  
  58      /**
  59       * Sends a PSR-7 request and returns a PSR-7 response.
  60       *
  61       * @since 7.0.0
  62       *
  63       * @param RequestInterface $request The PSR-7 request.
  64       * @return ResponseInterface The PSR-7 response.
  65       *
  66       * @throws NetworkException If the WordPress HTTP request fails.
  67       */
  68  	public function sendRequest( RequestInterface $request ): ResponseInterface {
  69          $args = $this->prepare_wp_args( $request );
  70          $url  = (string) $request->getUri();
  71  
  72          $response = wp_safe_remote_request( $url, $args );
  73  
  74          if ( is_wp_error( $response ) ) {
  75              $message = sprintf(
  76                  /* translators: 1: HTTP method (e.g. GET, POST). 2: Request URL. 3: Error message. */
  77                  __( 'Network error occurred while sending %1$s request to %2$s: %3$s' ),
  78                  $request->getMethod(),
  79                  $url,
  80                  $response->get_error_message()
  81              );
  82              throw new NetworkException( $message ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
  83          }
  84  
  85          return $this->create_psr_response( $response );
  86      }
  87  
  88      /**
  89       * Sends a PSR-7 request with transport options and returns a PSR-7 response.
  90       *
  91       * @since 7.0.0
  92       *
  93       * @param RequestInterface $request The PSR-7 request.
  94       * @param RequestOptions   $options Transport options for the request.
  95       * @return ResponseInterface The PSR-7 response.
  96       *
  97       * @throws NetworkException If the WordPress HTTP request fails.
  98       */
  99  	public function sendRequestWithOptions( RequestInterface $request, RequestOptions $options ): ResponseInterface {
 100          $args = $this->prepare_wp_args( $request, $options );
 101          $url  = (string) $request->getUri();
 102  
 103          $response = wp_safe_remote_request( $url, $args );
 104  
 105          if ( is_wp_error( $response ) ) {
 106              $message = sprintf(
 107                  /* translators: 1: Request URL. 2: Error message. */
 108                  __( 'Network error occurred while sending request to %1$s: %2$s' ),
 109                  $url,
 110                  $response->get_error_message()
 111              );
 112  
 113              throw new NetworkException(
 114                  $message, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
 115                  $response->get_error_code() ? (int) $response->get_error_code() : 0
 116              );
 117          }
 118  
 119          return $this->create_psr_response( $response );
 120      }
 121  
 122      /**
 123       * Prepares WordPress HTTP API arguments from a PSR-7 request.
 124       *
 125       * @since 7.0.0
 126       *
 127       * @param RequestInterface    $request The PSR-7 request.
 128       * @param RequestOptions|null $options Optional transport options for the request.
 129       * @return array<string, mixed> WordPress HTTP API arguments.
 130       */
 131  	private function prepare_wp_args( RequestInterface $request, ?RequestOptions $options = null ): array {
 132          $args = array(
 133              'method'      => $request->getMethod(),
 134              'headers'     => $this->prepare_headers( $request ),
 135              'body'        => $this->prepare_body( $request ),
 136              'httpversion' => $request->getProtocolVersion(),
 137              'blocking'    => true,
 138          );
 139  
 140          if ( null !== $options ) {
 141              if ( null !== $options->getTimeout() ) {
 142                  $args['timeout'] = $options->getTimeout();
 143              }
 144  
 145              if ( null !== $options->getMaxRedirects() ) {
 146                  $args['redirection'] = $options->getMaxRedirects();
 147              }
 148          }
 149  
 150          return $args;
 151      }
 152  
 153      /**
 154       * Prepares headers for WordPress HTTP API.
 155       *
 156       * @since 7.0.0
 157       *
 158       * @param RequestInterface $request The PSR-7 request.
 159       * @return array<string, string> Headers array for WordPress HTTP API.
 160       */
 161  	private function prepare_headers( RequestInterface $request ): array {
 162          $headers = array();
 163  
 164          foreach ( $request->getHeaders() as $name => $values ) {
 165              $headers[ (string) $name ] = implode( ', ', $values );
 166          }
 167  
 168          return $headers;
 169      }
 170  
 171      /**
 172       * Prepares request body for WordPress HTTP API.
 173       *
 174       * @since 7.0.0
 175       *
 176       * @param RequestInterface $request The PSR-7 request.
 177       * @return string|null The request body.
 178       */
 179  	private function prepare_body( RequestInterface $request ): ?string {
 180          $body = $request->getBody();
 181  
 182          if ( $body->getSize() === 0 ) {
 183              return null;
 184          }
 185  
 186          if ( $body->isSeekable() ) {
 187              $body->rewind();
 188          }
 189  
 190          return (string) $body;
 191      }
 192  
 193      /**
 194       * Creates a PSR-7 response from a WordPress HTTP response.
 195       *
 196       * @since 7.0.0
 197       *
 198       * @param array<string, mixed> $wp_response WordPress HTTP API response array.
 199       * @return ResponseInterface PSR-7 response.
 200       */
 201  	private function create_psr_response( array $wp_response ): ResponseInterface {
 202          $status_code   = wp_remote_retrieve_response_code( $wp_response );
 203          $reason_phrase = wp_remote_retrieve_response_message( $wp_response );
 204          $headers       = wp_remote_retrieve_headers( $wp_response );
 205          $body          = wp_remote_retrieve_body( $wp_response );
 206  
 207          $response = $this->response_factory->createResponse( (int) $status_code, $reason_phrase );
 208  
 209          if ( $headers instanceof WP_HTTP_Requests_Response ) {
 210              $headers = $headers->get_headers();
 211          }
 212  
 213          if ( is_array( $headers ) || $headers instanceof Traversable ) {
 214              foreach ( $headers as $name => $value ) {
 215                  $response = $response->withHeader( $name, $value );
 216              }
 217          }
 218  
 219          if ( ! empty( $body ) ) {
 220              $stream   = $this->stream_factory->createStream( $body );
 221              $response = $response->withBody( $stream );
 222          }
 223  
 224          return $response;
 225      }
 226  }


Generated : Sat Jun 13 09:38:55 2026 Cross-referenced by PHPXref