2017-07-11 50 views
5

我需要使用firebase函数来实现soap web服务。 我发现了一个名为soap-node soap-module-github的模块,它看起来很有前途,因为它与express集成在一起,firebase表示它使用express来表示http调用,但问题在于,我不知道如何将该模块与firebase函数进行集成, firebase函数是客户端发出http调用的处理程序,任何帮助都将非常有用。如何使用Firebase的云端函数编写SOAP服务?

这里是我已成功地创建至今代码:

var fs = require('fs'), 
    soap = require('soap'), 
    express = require('express'), 
    lastReqAddress; 
    var server = express(); 
    service = { 
     StockQuoteService: { 
      StockQuotePort: { 
       GetLastTradePrice: function (args, cb, soapHeader) { 
        if (soapHeader) 
         return { 
          price: soapHeader.SomeToken 
         }; 
        if (args.tickerSymbol === 'trigger error') { 
         throw new Error('triggered server error'); 
        } else if (args.tickerSymbol === 'Async') { 
         return cb({ 
          price: 19.56 
         }); 
        } else if (args.tickerSymbol === 'SOAP Fault v1.2') { 
         throw { 
          Fault: { 
           Code: { 
            Value: "soap:Sender", 
            Subcode: { 
             value: "rpc:BadArguments" 
            } 
           }, 
           Reason: { 
            Text: "Processing Error" 
           } 
          } 
         }; 
        } else if (args.tickerSymbol === 'SOAP Fault v1.1') { 
         throw { 
          Fault: { 
           faultcode: "soap:Client.BadArguments", 
           faultstring: "Error while processing arguments" 
          } 
         }; 
        } else { 
         return { 
          price: 19.56 
         }; 
        } 
       }, 

       SetTradePrice: function (args, cb, soapHeader) {}, 

       IsValidPrice: function (args, cb, soapHeader, req) { 
        lastReqAddress = req.connection.remoteAddress; 

        var validationError = { 
         Fault: { 
          Code: { 
           Value: "soap:Sender", 
           Subcode: { 
            value: "rpc:BadArguments" 
           } 
          }, 
          Reason: { 
           Text: "Processing Error" 
          }, 
          statusCode: 500 
         } 
        }; 

        var isValidPrice = function() { 
         var price = args.price; 
         if (isNaN(price) || (price === ' ')) { 
          return cb(validationError); 
         } 

         price = parseInt(price, 10); 
         var validPrice = (price > 0 && price < Math.pow(10, 5)); 
         return cb(null, { 
          valid: validPrice 
         }); 
        }; 

        setTimeout(isValidPrice, 10); 
       } 
      } 
     } 
    }; 
    var wsdl = fs.readFileSync(__dirname + '/../wsdl/stockquote.wsdl', 'utf-8').toString(); 
    server = express(); 

    soapServer = soap.listen(server, '/stockquote', service, wsdl); 

这里是stockquote.wsdl:

<wsdl:definitions name="StockQuote" 
     targetNamespace="http://example.com/stockquote.wsdl" 
     xmlns:tns="http://example.com/stockquote.wsdl" 
     xmlns:xsd1="http://example.com/stockquote.xsd" 
     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> 

<wsdl:types> 
    <xsd:schema targetNamespace="http://example.com/stockquote.xsd" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"> 
     <xsd:element name="TradePriceRequest"> 
      <xsd:complexType> 
       <xsd:all> 
        <xsd:element name="tickerSymbol" type="string"/> 
       </xsd:all> 
      </xsd:complexType> 
     </xsd:element> 
     <xsd:element name="TradePrice"> 
      <xsd:complexType> 
       <xsd:all> 
        <xsd:element name="price" type="float"/> 
       </xsd:all> 
      </xsd:complexType> 
     </xsd:element> 
     <xsd:element name="TradePriceSubmit"> 
      <xsd:complexType> 
       <xsd:all> 
        <xsd:element name="tickerSymbol" type="string"/> 
        <xsd:element name="price" type="float"/> 
       </xsd:all> 
      </xsd:complexType> 
     </xsd:element> 
     <xsd:element name="valid" type="boolean"/> 
    </xsd:schema> 
</wsdl:types> 

<wsdl:message name="GetLastTradePriceInput"> 
    <wsdl:part name="body" element="xsd1:TradePriceRequest"/> 
</wsdl:message> 

<wsdl:message name="GetLastTradePriceOutput"> 
    <wsdl:part name="body" element="xsd1:TradePrice"/> 
</wsdl:message> 

<wsdl:message name="SetTradePriceInput"> 
    <wsdl:part name="body" element="xsd1:TradePriceSubmit"/> 
</wsdl:message> 

<wsdl:message name="IsValidPriceInput"> 
    <wsdl:part name="body" element="xsd1:TradePrice"/> 
</wsdl:message> 

<wsdl:message name="IsValidPriceOutput"> 
    <wsdl:part name="body" element="xsd1:valid"/> 
</wsdl:message> 

<wsdl:portType name="StockQuotePortType"> 
    <wsdl:operation name="GetLastTradePrice"> 
     <wsdl:input message="tns:GetLastTradePriceInput"/> 
     <wsdl:output message="tns:GetLastTradePriceOutput"/> 
    </wsdl:operation> 
    <wsdl:operation name="SetTradePrice"> 
     <wsdl:input message="tns:SetTradePriceInput"/> 
    </wsdl:operation> 
    <wsdl:operation name="IsValidPrice"> 
     <wsdl:input message="tns:IsValidPriceInput"/> 
     <wsdl:output message="tns:IsValidPriceOutput"/> 
    </wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType"> 
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
    <wsdl:operation name="GetLastTradePrice"> 
     <soap:operation soapAction="http://example.com/GetLastTradePrice"/> 
     <wsdl:input> 
      <soap:body use="literal"/> 
     </wsdl:input> 
     <wsdl:output> 
      <soap:body use="literal"/> 
     </wsdl:output> 
    </wsdl:operation> 
    <wsdl:operation name="SetTradePrice"> 
     <soap:operation soapAction="http://example.com/SetTradePrice"/> 
     <wsdl:input> 
      <soap:body use="literal"/> 
     </wsdl:input> 
    </wsdl:operation> 
    <wsdl:operation name="IsValidPrice"> 
     <soap:operation soapAction="http://example.com/IsValidPrice"/> 
     <wsdl:input> 
      <soap:body use="literal"/> 
     </wsdl:input> 
    </wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="StockQuoteService"> 
    <wsdl:port name="StockQuotePort" binding="tns:StockQuoteSoapBinding"> 
     <soap:address location="http://localhost:5002/stockquote"/> 
    </wsdl:port> 
</wsdl:service> 

我用Google搜索非常好,我只是没有找到一些路径,我也搜索谷歌的功能和他们与肥皂的集成,因为火力基地功能只是用于火力点的谷歌云功能

+0

您是否找到解决方案? – faruk

回答

2

在为node-soap源代码偷看,你应该能够直接通过_requestListener到云功能的onRequest功能:

exports.stockquote = functions.https.onRequest(soapServer._requestListener) 
+0

我试过这个,并得到错误'不能读取未定义的属性'日志' – faruk

1

您可以使用express与现在的云功能:

server = express(); 
server.listen(5002, function() { 
    soap.listen(server, '/stockquote', service, wsdl); 
}); 

exports.stockquote = functions.https.onRequest(server); 

把在firebase.json中的路线:

​​

当在客户端上使用javascript进行测试时don'别忘了更改端点覆盖localhost在WSDL:

var soap = require('soap'); 
var url = 'https://[your-project-id].firebaseapp.com/stockquote?wsdl'; 
var args = {tickerSymbol: 'some symbol', price: 100.0}; 

var options = { 
    'endpoint' : 'https://[your-project-id].firebaseapp.com/stockquote' 
}; 

soap.createClient(url, options, function(err, client) { 
    if (err) throw err; 
    //print service in json 
    console.log(client.describe()); 
    client.GetLastTradePrice(args, function(err, result) { 
     if(err) 
      console.log("err = "+ err.message); 
     console.log(result); 
     res.status(200).send(result); 
    }); 
}); 
2

您是在正确的道路上,

如果您希望您的GCF路服务器是http://myfunctions.domain.com/stockquote/

那么你的最后在js文件行应该是 soapServer = soap.listen(server, '/', service, wsdl)并在那之后,在你的谷歌云功能index.js输入:

exports.stockquote = functions.https.onRequest(server)

您将不得不确保您的SOAP请求在末尾以作为末尾的斜杠进入端点。如果您无法控制现有客户端,则可以添加自己的URL处理程序,该处理程序将查看该URL并在您的功能收到的URL中添加/

即: exports.stockquote = functions.https.onRequest(gcfURLHandler(server));

其中gcfURLHandler被定义为

function gcfURLHandler(handler){ 
    return (req, res) => { 
     if(!req.url || !req.path) { 
      req.url = "/" + (req.url || ''); 
     } 
     handler(req, res) 
    } 
} 

从评论here想通了这一点。 (其中也有原始代码中的其他提示)

我上周正在处理这个问题,看到了未解决的问题。花了很多时间挖掘,最终弄清楚了。希望这可以帮助其他人也这样做!

相关问题