nt route. * @param array $data Data. * * @return mixed */ public function head( $path, $data = array() ) { try { return $this->request( $path, $data, 'head' ); } catch ( Exception $e ) { return new WP_Error( $e->getCode(), $e->getMessage() ); } } /** * Make a GET API Call * * @param string $path Endpoint route. * @param array $data Data. * * @return mixed */ public function delete( $path, $data = array() ) { try { return $this->request( $path, $data, 'delete' ); } catch ( Exception $e ) { return new WP_Error( $e->getCode(), $e->getMessage() ); } } /** * Make a PURGE API Call * * @since 2.1.0 * * @param string $path Endpoint route. * @param array $data Data. * * @return mixed */ public function purge( $path, $data = array() ) { try { return $this->request( $path, $data, 'purge' ); } catch ( Exception $e ) { return new WP_Error( $e->getCode(), $e->getMessage() ); } } /** * Make a PUT API Call * * @since 3.3.1 * * @param string $path Endpoint route. * @param array $data Data. * * @return mixed */ public function put( $path, $data = array() ) { try { return $this->request( $path, $data, 'put' ); } catch ( Exception $e ) { return new WP_Error( $e->getCode(), $e->getMessage() ); } } /** * Make an API Request * * @since 1.8.1 Timeout for non-blocking changed from 0.1 to 2 seconds. * * @param string $path Path. * @param array $data Arguments array. * @param string $method Method. * * @return array|mixed|object */ public function request( $path, $data = array(), $method = 'post' ) { $url = $this->get_api_url( $path ); $this->sign_request(); $url = add_query_arg( $this->get_args, $url ); if ( ! in_array( $method, array( 'post', 'patch', 'delete', 'put' ), true ) ) { $url = add_query_arg( $data, $url ); } $args = array( 'headers' => $this->headers, 'sslverify' => false, 'method' => strtoupper( $method ), 'timeout' => $this->timeout, ); if ( ! $args['timeout'] || 2 === $args['timeout'] ) { $args['blocking'] = false; } $this->logger->log( "WPHB API: Sending request to $url", 'api' ); $this->logger->log( 'WPHB API: Arguments:', 'api' ); $this->logger->log( $this->sanitize_args_for_logging( $args ), 'api' ); switch ( strtolower( $method ) ) { case 'patch': case 'delete': case 'put': case 'post': if ( is_array( $data ) ) { $args['body'] = array_merge( $data, $this->post_args ); } else { $args['body'] = $data; } $response = wp_remote_post( $url, $args ); break; case 'head': $response = wp_remote_head( $url, $args ); break; case 'get': $response = wp_remote_get( $url, $args ); break; case 'purge': default: $response = wp_remote_request( $url, $args ); break; } $this->logger->log( 'WPHB API: Response:', 'api' ); $this->logger->log( $response, 'api' ); return $response; } /** * Sign request. */ protected function sign_request() {} /** * Sanitize arguments for logging by redacting sensitive headers. * * @since 3.18.1 * * @param array $args Request arguments to sanitize. * @return array Sanitized arguments safe for logging. */ private function sanitize_args_for_logging( $args ) { // Nothing to sanitize. if ( empty( $args['headers'] ) || ! is_array( $args['headers'] ) ) { return $args; } /** * Filter the list of sensitive headers to redact from logs. * * @since 3.18.1 * * @param array $sensitive_headers Array of header names to redact. */ $sensitive_headers = apply_filters( 'wphb_sensitive_headers', array( 'X-Auth-Key', 'X-Auth-Email', 'Authorization', ) ); // Build case-insensitive lookup map for performance. $sensitive_lookup = array_fill_keys( array_map( 'strtolower', $sensitive_headers ), true ); // Redact sensitive headers. foreach ( $args['headers'] as $header => $value ) { if ( isset( $sensitive_lookup[ strtolower( $header ) ] ) ) { $args['headers'][ $header ] = '*** REDACTED PER SECURITY POLICY ***'; } } return $args; } }