Node.js : SOAP XML 웹 서비스를 사용하는 방법


99

node.js로 SOAP XML 웹 서비스를 사용하는 가장 좋은 방법이 무엇인지 궁금합니다.

감사!


node-soap을 사용하고 사용 방법을 알아 낸 경우 wsdl을 만드는 데 도움을 줄 수 있습니까? wsdl을 작성하는 방법에 대한 생성기 또는 좋은 자습서가 있습니까? stackoverflow.com/questions/32480481/...
앤디 기가에게

.NET WCF 서비스 호출에 대한 예제가 필요한 경우 내 대답 stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

답변:


83

그다지 많은 옵션이 없습니다.

다음 중 하나를 사용하고 싶을 것입니다.


3
감사. 설치 노드 비누 문제가 노드 해외 거주자 설치 실패 = (인해
WHITECOLOR

빌드하려면 expat 개발 헤더가 필요합니다.
Juicy Scripter 2011

헤더에 대한 문제를 발견했지만 어디서 컴파일해야할지 모르겠습니다. 설명해 주시겠습니까?
WHITECOLOR dec.

1
아마도 OS 용 패키지 관리 도구를 통해 얻을 수 있습니다. 예를 들어 Ubuntu에서sudo apt-get install libexpat1-dev
Juicy Scripter

1
@RobertBroden, 업데이트 주셔서 감사합니다. 다음에 답변을 수정 (또는 수정 제안) 해주세요!
Juicy Scripter 2016

31

나는 대안이 될 것이라고 생각합니다.

  • SoapUI ( http://www.soapui.org ) 와 같은 도구를 사용하여 입력 및 출력 xml 메시지를 기록합니다.
  • 노드 요청 ( https://github.com/mikeal/request )을 사용 하여 웹 서비스에 요청을 보낼 (POST) 입력 xml 메시지를 형성합니다 (ejs ( http://embeddedjs.com 과 같은 표준 자바 스크립트 템플릿 메커니즘) / ) 또는 콧수염 ( https://github.com/janl/mustache.js )이 여기에서 도움이 될 수 있습니다) 그리고 마지막으로
  • XML 파서를 사용하여 응답 데이터를 JavaScript 개체로 deserialize

예, 이것은 다소 더럽고 낮은 수준의 접근 방식이지만 문제없이 작동합니다.


4
안타깝게도 이것은 Node.js와 SOAP와 상호 작용하는 가장 안정적인 방법입니다. 내가 사용해야하는 소수의 API에 대해 비누 요청을 제대로 수행하는 단일 비누 라이브러리를 아직 찾지 못했습니다.
AlbertEngelB

1
100 % 더럽지 만 결과를 얻었습니다)))
markkillah

정확히 입력 xml`을 형성한다는 것은 무엇을 의미합니까?
timaschew

그래, 여전히 위에서 언급 한 libs가 아닌 것을 확인할 수 있습니다.
결과 someuser

나는 "양식 입력 XML"수단이 바로 "text / xml"의 Content-Type을주고 생각
SSH이

22

경우 node-soap당신을 위해 일을하지 않습니다, 단지 사용하는 node request모듈을하고 필요한 경우 다음 JSON으로 XML을 변환합니다.

내 요청이 작동 node-soap하지 않았고 내 리소스를 초과하는 유료 지원 외에 해당 모듈에 대한 지원이 없습니다. 그래서 다음을 수행했습니다.

  1. 내 Linux 컴퓨터에 SoapUI 를 다운로드 했습니다 .
  2. WSDL xml을 로컬 파일에 복사했습니다.
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. SoapUI에서 나는에 가서 File > New Soap project내 업로드 wsdl_file.xml.
  4. 네비게이터에서 서비스 중 하나를 확장하고 요청을 마우스 오른쪽 버튼으로 클릭하고을 클릭했습니다 Show Request Editor.

거기에서 요청을 보내고 제대로 작동하는지 확인할 수 있으며 Raw또는 HTML데이터를 사용하여 외부 요청을 작성할 수도 있습니다 .

내 요청에 대한 SoapUI의 원시

POST http://192.168.0.28:10005/MainService/WindowsService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://Main.Service/AUserService/GetUsers"
Content-Length: 303
Host: 192.168.0.28:10005
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

SoapUI의 XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:qtre="http://Main.Service">
   <soapenv:Header/>
   <soapenv:Body>
      <qtre:GetUsers>
         <qtre:sSearchText></qtre:sSearchText>
      </qtre:GetUsers>
   </soapenv:Body>
</soapenv:Envelope> 

위를 사용하여 다음을 빌드했습니다 node request.

var request = require('request');
let xml =
`<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:qtre="http://Main.Service">
   <soapenv:Header/>
   <soapenv:Body>
      <qtre:GetUsers>
         <qtre:sSearchText></qtre:sSearchText>
      </qtre:GetUsers>
   </soapenv:Body>
</soapenv:Envelope>`

var options = {
  url: 'http://192.168.0.28:10005/MainService/WindowsService?wsdl',
  method: 'POST',
  body: xml,
  headers: {
    'Content-Type':'text/xml;charset=utf-8',
    'Accept-Encoding': 'gzip,deflate',
    'Content-Length':xml.length,
    'SOAPAction':"http://Main.Service/AUserService/GetUsers"
  }
};

let callback = (error, response, body) => {
  if (!error && response.statusCode == 200) {
    console.log('Raw result', body);
    var xml2js = require('xml2js');
    var parser = new xml2js.Parser({explicitArray: false, trim: true});
    parser.parseString(body, (err, result) => {
      console.log('JSON result', result);
    });
  };
  console.log('E', response.statusCode, response.statusMessage);  
};
request(options, callback);

감사합니다 @jtlindsey. 하지만 405 메서드가 response.statusCode, response.statusMessage로 허용되지 않습니다. 혹시이 문제를 해결하는 방법을 알고 계십니까?
Sujoy

내 URL에 문제가 있습니다. SOAPUI에서 생성 한 끝점 대신 원래 URL을 사용하고있었습니다. 위의 코드에 감사드립니다.
Sujoy

17

나는 soap, wsdl 및 Node.js를 사용했습니다. npm install soap

server.js원격 클라이언트가 사용할 SOAP 서비스를 정의하는 라는 노드 서버를 작성하십시오 . 이 비누 서비스는 체중 (kg)과 키 (m)를 기준으로 체질량 지수를 계산합니다.

const soap = require('soap');
const express = require('express');
const app = express();
/**
 * this is remote service defined in this file, that can be accessed by clients, who will supply args
 * response is returned to the calling client
 * our service calculates bmi by dividing weight in kilograms by square of height in metres
 */
const service = {
  BMI_Service: {
    BMI_Port: {
      calculateBMI(args) {
        //console.log(Date().getFullYear())
        const year = new Date().getFullYear();
        const n = args.weight / (args.height * args.height);
        console.log(n);
        return { bmi: n };
      }
    }
  }
};
// xml data is extracted from wsdl file created
const xml = require('fs').readFileSync('./bmicalculator.wsdl', 'utf8');
//create an express server and pass it to a soap server
const server = app.listen(3030, function() {
  const host = '127.0.0.1';
  const port = server.address().port;
});
soap.listen(server, '/bmicalculator', service, xml);

다음으로에 client.js정의 된 SOAP 서비스를 사용할 파일을 만듭니다 server.js. 이 파일은 SOAP 서비스에 대한 인수를 제공하고 SOAP의 서비스 포트 및 엔드 포인트로 URL을 호출합니다.

const express = require('express');
const soap = require('soap');
const url = 'http://localhost:3030/bmicalculator?wsdl';
const args = { weight: 65.7, height: 1.63 };
soap.createClient(url, function(err, client) {
  if (err) console.error(err);
  else {
    client.calculateBMI(args, function(err, response) {
      if (err) console.error(err);
      else {
        console.log(response);
        res.send(response);
      }
    });
  }
});

wsdl 파일은 원격 웹 서비스에 액세스하는 방법을 정의하는 데이터 교환을위한 xml 기반 프로토콜입니다. wsdl 파일 호출bmicalculator.wsdl

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

  <message name="getBMIRequest">
    <part name="weight" type="xsd:float"/>
    <part name="height" type="xsd:float"/>
  </message>

  <message name="getBMIResponse">
    <part name="bmi" type="xsd:float"/>
  </message>

  <portType name="Hello_PortType">
    <operation name="calculateBMI">
      <input message="tns:getBMIRequest"/>
      <output message="tns:getBMIResponse"/>
    </operation>
  </portType>

  <binding name="Hello_Binding" type="tns:Hello_PortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="calculateBMI">
      <soap:operation soapAction="calculateBMI"/>
      <input>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/>
      </input>
      <output>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/>
      </output>
    </operation>
  </binding>

  <service name="BMI_Service">
    <documentation>WSDL File for HelloService</documentation>
    <port binding="tns:Hello_Binding" name="BMI_Port">
      <soap:address location="http://localhost:3030/bmicalculator/" />
    </port>
  </service>
</definitions>

도움이되기를 바랍니다.


1
정말 고맙습니다. 그러나 "res.send (response);"를 제거해야했습니다. 클라이언트에서, 서버 파일의 마지막 줄에 "`".
Subhashi

13

Node.js를 사용하여 SOAP 서비스에 원시 XML을 보내는 가장 간단한 방법은 Node.js http 구현을 사용하는 것입니다. 이렇게 생겼어요.

var http = require('http');
var http_options = {
  hostname: 'localhost',
  port: 80,
  path: '/LocationOfSOAPServer/',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': xml.length
  }
}

var req = http.request(http_options, (res) => {
  console.log(`STATUS: ${res.statusCode}`);
  console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
    console.log(`BODY: ${chunk}`);
  });

  res.on('end', () => {
    console.log('No more data in response.')
  })
});

req.on('error', (e) => {
  console.log(`problem with request: ${e.message}`);
});

// write data to request body
req.write(xml); // xml would have been set somewhere to a complete xml document in the form of a string
req.end();

xml 변수를 문자열 형식의 원시 xml로 정의했을 것입니다.

그러나 원시 xml을 보내는 대신 Node.js를 통해 SOAP 서비스와 상호 작용하고 일반 SOAP 호출을 수행하려는 경우 Node.js 라이브러리 중 하나를 사용하십시오. 나는 node-soap을 좋아 합니다 .


1
#Halfstop, node-soap을 사용하여 POST 요청을 만드는 방법을 알려주시겠습니까?
Abhishek saini

@Abhisheksaini 위의 예는 게시물입니다.
하프 스톱

@Halfstop 친절하게 요청에 SOAPAction을 포함하는 방법을 알려주세요.
Sohail

12

필요한 엔드 포인트의 수에 따라 수동으로 수행하는 것이 더 쉬울 수 있습니다.

나는 10 개의 라이브러리 "soap nodejs"를 시도했다. 마침내 수동으로한다.


나는 WSDL 경로에 액세스 노드 비누를 시도했지만 같은 일이 당신이 당신이 그것을 않았다 방법에 대한 내 질문에 대답 할 수 PHP에서 작동하지만, 그것은 일, 난 오류가 계속 나던 stackoverflow.com/questions/39943122/...
아마르 아즈

8

10 개 이상의 추적 WebApis (Tradetracker, Bbelboon, Affilinet, Webgains, ...)에서 "soap"패키지 ( https://www.npmjs.com/package/soap )를 성공적으로 사용했습니다 .

문제는 일반적으로 프로그래머가 연결 또는 인증을 위해 필요한 원격 API에 대해 많이 조사하지 않는다는 사실에서 발생합니다.

예를 들어 PHP는 HTTP 헤더에서 쿠키를 자동으로 재전송하지만 '노드'패키지를 사용할 때는 명시 적으로 설정해야합니다 (예 : 'soap-cookie'패키지) ...


soap-cookie를 사용하면 노드에서 발생한 인증 문제를 우회하는 데 도움이되었습니다. 감사합니다!
nicolasdaudin


5

나는 node net 모듈을 사용하여 웹 서비스에 대한 소켓을 열었습니다.

/* on Login request */
socket.on('login', function(credentials /* {username} {password} */){   
    if( !_this.netConnected ){
        _this.net.connect(8081, '127.0.0.1', function() {
            logger.gps('('+socket.id + ') '+credentials.username+' connected to: 127.0.0.1:8081');
            _this.netConnected = true;
            _this.username = credentials.username;
            _this.password = credentials.password;
            _this.m_RequestId = 1;
            /* make SOAP Login request */
            soapGps('', _this, 'login', credentials.username);              
        });         
    } else {
        /* make SOAP Login request */
        _this.m_RequestId = _this.m_RequestId +1;
        soapGps('', _this, 'login', credentials.username);          
    }
});

SOAP 요청 보내기

/* SOAP request func */
module.exports = function soapGps(xmlResponse, client, header, data) {
    /* send Login request */
    if(header == 'login'){
        var SOAP_Headers =  "POST /soap/gps/login HTTP/1.1\r\nHost: soap.example.com\r\nUser-Agent: SOAP-client/SecurityCenter3.0\r\n" +
                            "Content-Type: application/soap+xml; charset=\"utf-8\"";        
        var SOAP_Envelope=  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                            "<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:n=\"http://www.example.com\"><env:Header><n:Request>" +
                            "Login" +
                            "</n:Request></env:Header><env:Body>" +
                            "<n:RequestLogin xmlns:n=\"http://www.example.com.com/gps/soap\">" +
                            "<n:Name>"+data+"</n:Name>" +
                            "<n:OrgID>0</n:OrgID>" +                                        
                            "<n:LoginEntityType>admin</n:LoginEntityType>" +
                            "<n:AuthType>simple</n:AuthType>" +
                            "</n:RequestLogin></env:Body></env:Envelope>";

        client.net.write(SOAP_Headers + "\r\nContent-Length:" + SOAP_Envelope.length.toString() + "\r\n\r\n");
        client.net.write(SOAP_Envelope);
        return;
    }

Soap 응답 구문 분석, 모듈 사용-xml2js

var parser = new xml2js.Parser({
    normalize: true,
    trim: true,
    explicitArray: false
});
//client.net.setEncoding('utf8');

client.net.on('data', function(response) {
    parser.parseString(response);
});

parser.addListener('end', function( xmlResponse ) {
    var response = xmlResponse['env:Envelope']['env:Header']['n:Response']._;
    /* handle Login response */
    if (response == 'Login'){
        /* make SOAP LoginContinue request */
        soapGps(xmlResponse, client, '');
    }
    /* handle LoginContinue response */
    if (response == 'LoginContinue') {
        if(xmlResponse['env:Envelope']['env:Body']['n:ResponseLoginContinue']['n:ErrCode'] == "ok") {           
            var nTimeMsecServer = xmlResponse['env:Envelope']['env:Body']['n:ResponseLoginContinue']['n:CurrentTime'];
            var nTimeMsecOur = new Date().getTime();
        } else {
            /* Unsuccessful login */
            io.to(client.id).emit('Error', "invalid login");
            client.net.destroy();
        }
    }
});

누군가에게 도움이되기를 바랍니다.


1
http 모듈을 사용하는 대신이 작업을 수행하는 이유는 무엇입니까?
Will Munn

0

에 추가 김 .J의 솔루션 : 추가 할 수있는 preserveWhitespace=true공백 오류를 방지하기 위해. 이렇게 :

soap.CreateClient(url,preserveWhitespace=true,function(...){

0

wsdlrdr도 사용할 수 있습니다. EasySoap은 기본적으로 몇 가지 추가 방법으로 wsdlrdr을 다시 작성합니다. easysoap에는 wsdlrdr에서 사용할 수있는 getNamespace 메소드가 없습니다.



0

일회성 변환이 필요한 경우 https://www.apimatic.io/dashboard?modal=transform을 사용하면 무료 계정을 만들어이 작업을 수행 할 수 있습니다 (제휴가 필요하지 않습니다.

Swagger 2.0으로 변환하면 다음을 사용하여 js lib를 만들 수 있습니다.

$ wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.20/swagger-codegen-cli-3.0.20.jar \
  -O swagger-codegen-cli.jar
$ java -jar swagger-codegen-cli.jar generate \
  -l javascript -i orig.wsdl-Swagger20.json -o ./fromswagger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.