Custom endpoint that returns an xml

By default, the output returned by your endpoint/callback will always be sent as a JSON-encoded string (and the Content-Type header would also be/contain application/json), so you can’t use that callback for sending an XML feed.

However, you can use the rest_pre_serve_request hook if you want your REST API route to serve a different type of content like the XML feed in your case.

So for example, you can do:

  1. Set your callback (smg_feed()) to return the XML data which will be echoed in the maybe_smg_feed() below: (note that the permission_callback should always be set, check the REST API handbook for more details)

    function smg_feed( $request ) {
        // ... your code ...
        return 'your XML data';
    }
    
    add_action( 'rest_api_init', function () {
        register_rest_route( 'smg/v1', 'feed', [
            'methods'             => 'GET',
            'callback'            => 'smg_feed', // make sure it returns an XML string
            'permission_callback' => '__return_true',
        ]);
    });
    
  2. Then send the XML response like so:

    function maybe_smg_feed( $served, $result, $request, $server ) {
        // Bail if the route of the current REST API request is not our custom route.
        if ( '/smg/v1/feed' !== $request->get_route() ||
            // Also check that the callback is smg_feed().
            'smg_feed' !== $request->get_attributes()['callback'] ) {
            return $served;
        }
    
        // Send headers.
        $server->send_header( 'Content-Type', 'text/xml' );
    
        // Echo the XML that's returned by smg_feed().
        echo $result->get_data();
    
        // And then exit.
        exit;
    }
    add_filter( 'rest_pre_serve_request', 'maybe_smg_feed', 10, 4 );
    

Alternatively (as I mentioned in the original answer), without using the REST API (which does work), you can use add_feed() to deliver the XML feed.

( PS: Thanks to @TimothyJacobs for his help/comment. 🙂 )

Leave a Comment