Search code examples
node.jssoapsoapserver

How do I get a client's IP address from inside a soap service?(nodejs)


I am written a soapService using the soap package, I'm passing an express server to it.

The problem is that the server can get requests from 2 different network interfaces, and I want which one the request came from.

My solution is to get client's IP and determine which interface it came from using

require("os").NetworkInterfaces()

but I couldn't find how to get a client's IP

I tried: this.req.ip, this.httpHeaders["x-forwarded-for"] || this.req.connection.remoteAddres but it comes as undefined

Edit: I want to add a minimal example for testing.

3 files are created: soapserver.js (that includes the soap service where I want to get the ip from inside of it) client.js (to call the soapservice) check_username.wsdl (used to create the service)

soapserver.js:

var soap = require('soap');
var http = require('http');
const util = require('util');
const app = require("express")()

var myService = {
    CheckUserName_Service: {
        CheckUserName_Port: {
            checkUserName: function(args, soapCallback) { 
                console.log('checkUserName: Entering function..');
                console.log(args);
                /*
                 * Where I'm trying to get clietn's IP address
                 */
                soapCallback("{'username found'}");
            }
        }
    }   
};


var xml = require('fs').readFileSync('check_username.wsdl', 'utf8');
var server = require("http").Server(app);    
app.get('/', (req, res) => {
    res.send("Hello World!");
    console.log(req);
    console.log(req.connection.remoteAddress);
    console.log(req.ip);
});

var port = 8000;
server.listen(port);

var soapServer = soap.listen(server, '/test', myService, xml);
soapServer.log = function(type, data) {
    console.log('Type: ' + type + ' data: ' + data);
};

console.log('SOAP service listening on port ' + port);

client.js:

"use strict";

var soap = require('strong-soap').soap;
var url = 'http://localhost:8000/test?wsdl';

var options = { endpoint: 'http://localhost:8000/test'};
var requestArgs = { userName: "TEST_USER" };
soap.createClient(url, options, function(err, client) {
  if (err) {
      console.error("An error has occurred creating SOAP client: " , err);  
  } else {
      var description = client.describe();
      console.log("Client description:" , description);
      var method = client.checkUserName;
      method(requestArgs, function(err, result, envelope, soapHeader) {
        //response envelope
        console.log('Response Envelope: \n' + envelope);
        //'result' is the response body
        console.log('Result: \n' + JSON.stringify(result));
      });
  }
});

check_username.wsdl

<definitions name = "CheckUserNameService"
   targetNamespace = "http://www.examples.com/wsdl/CheckUserNameService.wsdl"
   xmlns = "http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns = "http://www.examples.com/wsdl/CheckUserNameService.wsdl"
   xmlns:xsd = "http://www.w3.org/2001/XMLSchema">

   <message name = "CheckUserNameRequest">
      <part name = "userName" type = "xsd:string"/>
   </message>
   <message name = "CheckUserNameResponse">
      <part name = "status" type = "xsd:string"/>
   </message>
   <portType name = "CheckUserName_PortType">
      <operation name = "checkUserName">
         <input message = "tns:CheckUserNameRequest"/>
         <output message = "tns:CheckUserNameResponse"/>
      </operation>
   </portType>

   <binding name = "CheckUserName_Binding" type = "tns:CheckUserName_PortType">
      <soap:binding style = "rpc"
         transport = "http://schemas.xmlsoap.org/soap/http"/>
      <operation name = "checkUserName">
         <soap:operation soapAction = "checkUserName"/>
         <input>
            <soap:body encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/" namespace = "urn:examples:CheckUserNameService" use = "encoded"/>
         </input>
         <output>
            <soap:body encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/" namespace = "urn:examples:CheckUserNameService" use = "encoded"/>
         </output>
      </operation>
   </binding>

   <service name = "CheckUserName_Service">
      <documentation>WSDL File for CheckUserNameService</documentation>
      <port binding = "tns:CheckUserName_Binding" name = "CheckUserName_Port">
         <soap:address
            location = "http://www.examples.com/CheckUserName/" />
      </port>
   </service>
</definitions>

Solution

  • I found a solution that works for my case and probably would be of use for someone wanting to do something similar.

    I have 2 potential solutions:

    1/ I modified 'node-soap' package, in server.js I passed the IP (from req Object) to _process than have it included in argument that are going to be passed obj.Body[methodName]["ip"] = ip;

    2/ The goal was to find which network interface is coming from, so the second solution involves binding the server to only one interface (instead of 0.0.0.0) and have one server by interface.

    I went with the former in my case.