2017-07-11 51 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想通了這一點。 (其中也有原始代碼中的其他提示)

我上週正在處理這個問題,看到了未解決的問題。花了很多時間挖掘,最終弄清楚了。希望這可以幫助其他人也這樣做!

相關問題