Make WordPress Core


Ignore:
Timestamp:
05/11/2017 06:18:00 PM (9 years ago)
Author:
jnylen0
Message:

REST API: Add endpoint for proxying requests to external oEmbed providers.

This endpoint is a prerequisite for the media widgets work (see ​https://github.com/xwp/wp-core-media-widgets).

Also use the new endpoint in the media modal instead of the parse-embed AJAX action.

Props westonruter, timmydcrawford, swissspidy, jnylen0.
Fixes #40450.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/oembed/controller.php

    r40564 r40628  
    1010         */
    1111        protected $server;
     12        protected static $editor;
     13        protected static $subscriber;
     14        const YOUTUBE_VIDEO_ID = 'OQSNhk5ICTI';
     15        const INVALID_OEMBED_URL = 'https://www.notreallyanoembedprovider.com/watch?v=awesome-cat-video';
     16
     17        public static function wpSetUpBeforeClass( $factory ) {
     18                self::$subscriber = $factory->user->create( array(
     19                        'role' => 'subscriber',
     20                ) );
     21                self::$editor = $factory->user->create( array(
     22                        'role'       => 'editor',
     23                        'user_email' => 'editor@example.com',
     24                ) );
     25        }
     26
     27        public static function wpTearDownAfterClass() {
     28                self::delete_user( self::$subscriber );
     29                self::delete_user( self::$editor );
     30        }
    1231
    1332        public function setUp() {
    … …  
    1938
    2039                do_action( 'rest_api_init', $this->server );
     40                add_filter( 'pre_http_request', array( $this, 'mock_embed_request' ), 10, 3 );
     41                $this->request_count = 0;
     42        }
     43
     44        public function tearDown() {
     45                parent::tearDown();
     46
     47                remove_filter( 'pre_http_request', array( $this, 'mock_embed_request' ), 10, 3 );
     48        }
     49
     50        /**
     51         * Count of the number of requests attempted.
     52         *
     53         * @var int
     54         */
     55        public $request_count = 0;
     56
     57        /**
     58         * Intercept oEmbed requests and mock responses.
     59         *
     60         * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.
     61         * @param mixed  $r       HTTP request arguments.
     62         * @param string $url     The request URL.
     63         * @return array Response data.
     64         */
     65        public function mock_embed_request( $preempt, $r, $url ) {
     66                unset( $preempt, $r );
     67
     68                $this->request_count += 1;
     69
     70                // Mock request to YouTube Embed.
     71                if ( false !== strpos( $url, self::YOUTUBE_VIDEO_ID ) ) {
     72                        return array(
     73                                'response' => array(
     74                                        'code' => 200,
     75                                ),
     76                                'body' => wp_json_encode(
     77                                        array(
     78                                                'version'          => '1.0',
     79                                                'type'             => 'video',
     80                                                'provider_name'    => 'YouTube',
     81                                                'provider_url'     => 'https://www.youtube.com',
     82                                                'thumbnail_width'  => 480,
     83                                                'width'            => 500,
     84                                                'thumbnail_height' => 360,
     85                                                'html'             => '<iframe width="500" height="375" src="https://www.youtube.com/embed/' . self::YOUTUBE_VIDEO_ID . '?feature=oembed" frameborder="0" allowfullscreen></iframe>',
     86                                                'author_name'      => 'Yosemitebear62',
     87                                                'thumbnail_url'    => 'https://i.ytimg.com/vi/' . self::YOUTUBE_VIDEO_ID . '/hqdefault.jpg',
     88                                                'title'            => 'Yosemitebear Mountain Double Rainbow 1-8-10',
     89                                                'height'           => 375,
     90                                        )
     91                                ),
     92                        );
     93                } else {
     94                        return array(
     95                                'response' => array(
     96                                        'code' => 404,
     97                                ),
     98                        );
     99                }
    21100        }
    22101
    … …  
    87166                $this->assertArrayHasKey( 'methods', $route[0] );
    88167                $this->assertArrayHasKey( 'args', $route[0] );
     168
     169                // Check proxy route registration.
     170                $this->assertArrayHasKey( '/oembed/1.0/proxy', $filtered_routes );
     171                $proxy_route = $filtered_routes['/oembed/1.0/proxy'];
     172                $this->assertCount( 1, $proxy_route );
     173                $this->assertArrayHasKey( 'callback', $proxy_route[0] );
     174                $this->assertArrayHasKey( 'permission_callback', $proxy_route[0] );
     175                $this->assertArrayHasKey( 'methods', $proxy_route[0] );
     176                $this->assertArrayHasKey( 'args', $proxy_route[0] );
    89177        }
    90178
    … …  
    349437                update_option( 'permalink_structure', '' );
    350438        }
     439
     440        public function test_proxy_without_permission() {
     441                // Test without a login.
     442                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     443                $response = $this->server->dispatch( $request );
     444
     445                $this->assertEquals( 400, $response->get_status() );
     446
     447                // Test with a user that does not have edit_posts capability.
     448                wp_set_current_user( self::$subscriber );
     449                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     450                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     451                $response = $this->server->dispatch( $request );
     452
     453                $this->assertEquals( 403, $response->get_status() );
     454                $data = $response->get_data();
     455                $this->assertEquals( $data['code'], 'rest_forbidden' );
     456        }
     457
     458        public function test_proxy_with_invalid_oembed_provider() {
     459                wp_set_current_user( self::$editor );
     460                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     461                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     462                $response = $this->server->dispatch( $request );
     463                $this->assertEquals( 404, $response->get_status() );
     464                $data = $response->get_data();
     465                $this->assertEquals( 'oembed_invalid_url', $data['code'] );
     466        }
     467
     468        public function test_proxy_with_invalid_type() {
     469                wp_set_current_user( self::$editor );
     470                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     471                $request->set_param( 'type', 'xml' );
     472                $response = $this->server->dispatch( $request );
     473
     474                $this->assertEquals( 400, $response->get_status() );
     475                $data = $response->get_data();
     476        }
     477
     478        public function test_proxy_with_valid_oembed_provider() {
     479                wp_set_current_user( self::$editor );
     480
     481                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     482                $request->set_param( 'url', 'https://www.youtube.com/watch?v=' . self::YOUTUBE_VIDEO_ID );
     483                $response = $this->server->dispatch( $request );
     484                $this->assertEquals( 200, $response->get_status() );
     485                $this->assertEquals( 1, $this->request_count );
     486
     487                // Subsequent request is cached and so it should not cause a request.
     488                $response = $this->server->dispatch( $request );
     489                $this->assertEquals( 1, $this->request_count );
     490
     491                // Test data object.
     492                $data = $response->get_data();
     493
     494                $this->assertNotEmpty( $data );
     495                $this->assertTrue( is_object( $data ) );
     496                $this->assertEquals( 'YouTube', $data->provider_name );
     497                $this->assertEquals( 'https://i.ytimg.com/vi/' . self::YOUTUBE_VIDEO_ID . '/hqdefault.jpg', $data->thumbnail_url );
     498        }
     499
     500        public function test_proxy_with_invalid_oembed_provider_no_discovery() {
     501                wp_set_current_user( self::$editor );
     502
     503                // If discover is false for an unkown provider, no discovery request should take place.
     504                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     505                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     506                $request->set_param( 'discover', 0 );
     507                $response = $this->server->dispatch( $request );
     508                $this->assertEquals( 404, $response->get_status() );
     509                $this->assertEquals( 0, $this->request_count );
     510        }
     511
     512        public function test_proxy_with_invalid_oembed_provider_with_default_discover_param() {
     513                wp_set_current_user( self::$editor );
     514
     515                // For an unkown provider, a discovery request should happen.
     516                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     517                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     518                $response = $this->server->dispatch( $request );
     519                $this->assertEquals( 404, $response->get_status() );
     520                $this->assertEquals( 1, $this->request_count );
     521        }
     522
     523        public function test_proxy_with_invalid_discover_param() {
     524                wp_set_current_user( self::$editor );
     525                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     526                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     527                $request->set_param( 'discover', 'notaboolean' );
     528
     529                $response = $this->server->dispatch( $request );
     530
     531                $this->assertEquals( 400, $response->get_status() );
     532                $data = $response->get_data();
     533                $this->assertEquals( $data['code'], 'rest_invalid_param' );
     534        }
    351535}
Note: See TracChangeset for help on using the changeset viewer.