如何使用Cloud Functions的Cloud Functions编写SOAP服务?

时间:2017-07-11 11:15:55

标签: web-services firebase soap google-cloud-functions

我需要使用firebase函数实现soap web服务。 我发现了一个名为soap-node soap-module-github的模块似乎很有希望,因为它与express集成,而firebase说它使用express来进行http调用,但问题在于,我不知道如何集成该模块使用firebase函数,firebase函数是客户端进行http调用的处理程序,任何帮助都会非常有用。

这是我到目前为止设法创建的代码:

    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了很好,我只是找不到路径,我还搜索了google功能和他们与soap的集成,因为firebase功能只是用于firebase的google云功能

3 个答案:

答案 0 :(得分:2)

查看node-soap的源代码,您应该可以直接将_requestListener传递给Cloud Function的onRequest函数:

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

答案 1 :(得分:2)

你走在正确的道路上,

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

然后你在js文件中的最后一行应该是 soapServer = soap.listen(server, '/', service, wsdl)然后在您的Google云计算功能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中找出这一点。 (在原始代码中也有其他提示)

上周我正在研究这个问题并且看到了未解决的问题。进行了大量的挖掘,最终弄明白了。希望这有助于其他人也希望这样做!

答案 2 :(得分:1)

您现在可以使用list()云功能:

express

将路线放入firebase.json:

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

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

使用javascript在客户端上进行测试时,请不要忘记更改端点以覆盖wsdl中的 "rewrites": [ { "source": "/stockquote", "function": "stockquote" } ]

localhost