$p['host'] . ( isset( $p['port'] ) ? ':' . $p['port'] : '' ), 'X-Forwarded-Proto' => $p['scheme'] ?? 'http' ); $url = self::custom_loopback() . ( $p['path'] ?? '/' ) . ( isset( $p['query'] ) ? '?' . $p['query'] : '' ); $p = wp_parse_url( $url ); } $port = isset( $p['port'] ) ? (int) $p['port'] : ( 'https' === ( $p['scheme'] ?? 'http' ) ? 443 : 80 ); self::$resolve = $loopback && 'custom' !== $loopback && ! empty( $p['host'] ) ? $p['host'] . ':' . $port . ':' . $loopback : ''; $pinned = false; $pin = function ( $handle ) use ( &$pinned ) { if ( '' !== self::$resolve && defined( 'CURLOPT_RESOLVE' ) ) { // Inside the HTTP API's own http_api_curl hook: pins this site's own host name to the loopback // address so the check reaches this server, not a CDN in front of it. TLS checks are unchanged. curl_setopt( $handle, CURLOPT_RESOLVE, array( self::$resolve ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt $pinned = true; } }; add_action( 'http_api_curl', $pin ); $t = microtime( true ); $res = wp_remote_get( $url, array( 'timeout' => $timeout, 'redirection' => 0, 'user-agent' => 'm' === $device ? self::UA_MOBILE : self::UA_DESKTOP, 'headers' => array_merge( array( 'Accept-Encoding' => 'gzip' ), $extra ), // the .htaccess rules serve the .gz copy only to gzip clients 'cookies' => array(), ) ); $ms = (int) round( ( microtime( true ) - $t ) * 1000 ); remove_action( 'http_api_curl', $pin ); self::$resolve = ''; $via = $loopback ? 'loopback' : 'public'; if ( is_wp_error( $res ) ) { return array( 'code' => 0, 'ms' => $ms, 'layer' => 'error', 'via' => $via, 'foreign' => array(), 'error' => $res->get_error_message() ); } if ( $loopback && 'custom' !== $loopback && ! $pinned ) { // not curl: there was no way to pin, so this went out like a public request return array( 'code' => 0, 'ms' => $ms, 'layer' => 'error', 'via' => $via, 'foreign' => array(), 'error' => 'no curl' ); } $code = (int) wp_remote_retrieve_response_code( $res ); $h = wp_remote_retrieve_headers( $res ); $body = (string) wp_remote_retrieve_body( $res ); $out = array( 'code' => $code, 'ms' => $ms, 'layer' => 200 === $code ? self::layer( $h, $body ) : 'http_' . $code, 'via' => $via, 'foreign' => self::foreign_cache( $h ), 'headers' => isset( $h['x-zeroconfig-cache'] ) ? 'ours' : 'none', 'server' => substr( (string) ( $h['server'] ?? '' ), 0, 60 ), 'browser' => isset( $h['cache-control'] ) || isset( $h['expires'] ) ? 'told' : 'none', // Cache-Control/Expires present? 'error' => '', ); if ( $with_body ) { $out['body'] = substr( $body, 0, 200 ); } return $out; } /** Which layer answered. Apache serves our files without PHP, and without mod_headers without our header. */ public static function layer( $headers, $body ) { if ( self::foreign_cache( $headers ) ) { return 'foreign'; // a CDN or host cache answered; whatever it replays (our header, our marker) is old news } $hit = strtoupper( (string) ( $headers['x-zeroconfig-cache'] ?? '' ) ); if ( 'HIT-HTACCESS' === $hit ) { return 'htaccess'; } if ( 'HIT' === $hit ) { return 'dropin'; } if ( 'HIT-WP' === $hit ) { return 'wp'; } if ( isset( $headers['x-zc-render'] ) ) { return 'miss'; // WordPress built it for this probe (the engine marks probe renders): not from cache } // Our stored copy without our header: Apache straight from disk on a host without mod_headers, // or a cache in front that kept our copy. The doctor tells them apart with the ping rule. A weak // signal only: white label and the footer filter can remove the note, so its absence means nothing. if ( preg_match( '/