返回 XML 作为 Loopback Remote Method 的响应

Returning XML in response from Loopback Remote Method

我正在使用环回连接器 REST (1.9.0) 并且有一个远程方法 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") }         
      }
   )

响应总是 return 一个转义的 JSON 字符串:

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

而不是

<foo xmlns="bar"/>

请注意,响应确实将 content-type 设置为 text/xml。

如果我将接受:header 设置为 "text/xml",我总是会收到 "Not Acceptable" 作为响应。

如果我设置

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

在 config.json 中,然后我得到一个 500 错误:

SyntaxError: Unexpected token <

我认为 "xml: true" 属性 只是导致响应解析器尝试将 JSON 转换为 XML。

如何在不解析的情况下将响应中的 return 环回 XML?是我将 return 类型设置为 "string" 的问题吗?如果是这样,Loopback 将识别为 XML 的类型是什么?

您需要在回复 object 中设置为 XML(稍后会详细介绍)。首先,将 return 类型设置为 'object' 如下所示:

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") }         
  }
)

接下来,您需要 return 一个 JSON object 和 XML 作为唯一的 属性。 toXML 应该是一个函数,它 return 是 XML 的字符串表示形式。如果将接受 header 设置为 "text/xml",则响应应为 XML。见下文:

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

您仍然需要在 config.json 中启用 XML,因为默认情况下它是禁用的:

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

请参阅 https://github.com/strongloop/strong-remoting/blob/4b74a612d3c969d15e3dcc4a6d978aa0514cd9e6/lib/http-context.js#L393 以了解有关其内部工作原理的更多信息。

我最近 运行 尝试在 Loopback 3.x 中为 Twilio 语音呼叫创建动态响应。在 model.remoteMethod 调用中,显式指定 return 类型和内容类型,如下所示:

model.remoteMethod(
    "voiceResponse", {
        accepts: [{
            arg: 'envelopeId',
            type: 'number',
            required: true
        }],
        http: {
            path: '/speak/:envelopeId',
            "verb": 'post'
        },
        returns: [{
            arg: 'body',
            type: 'file',
            root: true
        }, {
            arg: 'Content-Type',
            type: 'string',
            http: {
                target: 'header'
            }
        }],

    }
)

通过回调函数让您的方法 return 同时具有 xml 和内容类型。请注意,回调中的第一个参数是 return 如果存在错误:

model.voiceResponse = function(messageEnvelopeId, callback) {

    app.models.messageEnvelope.findById(messageEnvelopeId, {
        include: ['messages']
    }).then(function(res) {
        let voiceResponse = new VoiceResponse();
        voiceResponse.say({
                voice: 'woman',
                language: 'en'
            },
            "This is a notification alert from your grow system. " + res.toJSON().messages.message
        )

        callback(null,
            voiceResponse.toString(), // returns xml document as a string
            'text/xml'
        );
    });
}