Search code examples
node.jsexpressloopbackjs

Returning XML in response from Loopback Remote Method


I am using the Loopback Connector REST (1.9.0) and have a remote method that returns XML:

   Foo.remoteMethod
   (  
      "getXml",
      {
         accepts: [            
            {arg: 'id', type: 'string', required: true }
         ],
         http: {path: '/:id/content', "verb": 'get'},
         returns: {"type": "string", root:true},
         rest: {"after": setContentType("text/xml") }         
      }
   )

The response always returns an escaped JSON string:

"<foo xmlns=\"bar\"/>" 

instead of

<foo xmlns="bar"/>

Note that the response does have the content-type set to text/xml.

If I set my Accept: header to "text/xml", I always get "Not Acceptable" as a response.

If I set

"rest": {
  "normalizeHttpPath": false,
  "xml": true
}

In config.json, then I get a 500 error:

SyntaxError: Unexpected token <

I think that the "xml: true" property is simply causing a response parser to try to convert JSON into XML.

How can I get Loopback to return the XML in the response without parsing it? Is the problem that I am setting the return type to "string"? If so, what it the type that Loopback would recognize as XML?


Solution

  • You need to set toXML in your response object (more on that in a bit). First, set the return type to 'object' as shown below:

    Foo.remoteMethod
    (  
      "getXml",
      {
         accepts: [            
            {arg: 'id', type: 'string', required: true }
         ],
         http: {path: '/:id/content', "verb": 'get'},
         returns: {"type": "object", root:true},
         rest: {"after": setContentType("text/xml") }         
      }
    )
    

    Next, you will need to return a JSON object with toXML as the only property. toXML should be a function that returns a string representation of your XML. If you set the Accept header to "text/xml" then the response should be XML. See below:

    Foo.getXml = function(cb) {
      cb(null, {
        toXML: function() {
          return '<something></something>';
        }
      });
    };
    

    You still need to enable XML in config.json because it's disabled by default:

    "remoting": {
      "rest": {
        "normalizeHttpPath": false,
        "xml": true
      }
    }
    

    See https://github.com/strongloop/strong-remoting/blob/4b74a612d3c969d15e3dcc4a6d978aa0514cd9e6/lib/http-context.js#L393 for more info on how this works under the hood.