How to use Cloud features for Firebase to record a SOAP service?

I need to implement a soapy web service using firebase functions. I found a module called soap- node soap-module-github that seems promising as it integrates with express and firebase says it uses express for http calls, but the problem is that I don’t know how to integrate this module is with firebase functions, since firebase functions are handlers of HTTP requests made by clients, any help would be very helpful.

Here is the code that I have managed to create so far:

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); 

here is 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> 

I am very good at googled, I just could not find a way, I also looked for google functions and their integration with soap, because firebase functions are just Google cloud functions used for firebase

+5
source share
3 answers

Peeking in the source code for node-soap , you should be able to directly pass the _requestListener function to the Cloud Function onRequest :

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

You are on the right track

If you want your GCF path for the server to be http://myfunctions.domain.com/stockquote/

then your last line in the js file should be soapServer = soap.listen(server, '/', service, wsdl) , and then after that in your Google Cloud function index.js enter:

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

You will need to make sure your SOAP requests go back to the endpoint with the end slash at the end. If you do not have control over existing customers, you can add a URL handler to your own handler that will look at the URL and add / to the URL your function received.

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

where gcfURLHandler is defined as

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

figured it out from the comment here . (which also has other tips in the source code)

I worked on this last week and saw an unanswered question. Took a lot of digging to finally figure it out. Hope this helps others who want to do the same!

+2
source

Now you can use express with cloud functions:

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

Put the route in firebase.json:

  "rewrites": [ { "source": "/stockquote", "function": "stockquote" } ] 

When testing on the client using javascript, remember to change the endpoint to override localhost in 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); }); }); 
+1
source

Source: https://habr.com/ru/post/1269716/


All Articles