Make WordPress Core


Ignore:
Timestamp:
05/11/2017 06:18:00 PM (7 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.