diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 9d4a5fec05..11b8897a2b 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -252,7 +252,11 @@ class WP_REST_Server { $send_no_cache_headers = apply_filters( 'rest_send_nocache_headers', is_user_logged_in() ); if ( $send_no_cache_headers ) { foreach ( wp_get_nocache_headers() as $header => $header_value ) { - $this->send_header( $header, $header_value ); + if ( empty( $header_value ) ) { + $this->remove_header( $header ); + } else { + $this->send_header( $header, $header_value ); + } } } @@ -1262,6 +1266,30 @@ class WP_REST_Server { } } + /** + * Removes an HTTP header from the current response. + * + * @since 4.8.0 + * @access public + * + * @param string $key Header key. + */ + public function remove_header( $key ) { + if ( function_exists( 'header_remove' ) ) { + // In PHP 5.3+ there is a way to remove an already set header. + header_remove( $key ); + } else { + // In PHP 5.2, send an empty header, but only as a last resort to + // override a header already sent. + foreach ( headers_list() as $header ) { + if ( 0 === stripos( $header, "$key:" ) ) { + $this->send_header( $key, '' ); + break; + } + } + } + } + /** * Retrieves the raw request entity (body). * diff --git a/tests/phpunit/includes/spy-rest-server.php b/tests/phpunit/includes/spy-rest-server.php index 58e3c3b521..b14e2ab7d1 100644 --- a/tests/phpunit/includes/spy-rest-server.php +++ b/tests/phpunit/includes/spy-rest-server.php @@ -31,6 +31,10 @@ class Spy_REST_Server extends WP_REST_Server { $this->sent_headers[ $header ] = $value; } + public function remove_header( $header ) { + unset( $this->sent_headers[ $header ] ); + } + /** * Override the dispatch method so we can get a handle on the request object. * diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 046d2b5f62..1cd9e68463 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -763,9 +763,16 @@ class Tests_REST_Server extends WP_Test_REST_TestCase { $headers = $this->server->sent_headers; foreach ( wp_get_nocache_headers() as $header => $value ) { + if ( empty( $value ) ) { + continue; + } + $this->assertTrue( isset( $headers[ $header ] ), sprintf( 'Header %s is not present in the response.', $header ) ); $this->assertEquals( $value, $headers[ $header ] ); } + + // Last-Modified should be unset as per #WP23021 + $this->assertFalse( isset( $headers['Last-Modified'] ), 'Last-Modified should not be sent.' ); } public function test_no_nocache_headers_on_unauthenticated_requests() {