Простейший пример SOAP


241

Какой простейший пример SOAP с использованием Javascript?

Чтобы быть максимально полезным, ответ должен:

  • Будьте функциональны (другими словами, фактически работайте)
  • Отправьте хотя бы один параметр, который можно установить в другом месте кода
  • Обработайте хотя бы одно значение результата, которое можно прочитать в другом месте кода
  • Работа с большинством современных версий браузера
  • Будьте максимально понятны и коротки, не используя внешнюю библиотеку.

5
Быть простым и понятным может конфликтовать с не использованием внешней библиотеки. Вы действительно хотите написать свой собственный конвертер классов WSDL -> JS?
mikemaccana

19
У меня есть вопрос: если бы я увидел этот вопрос как первого человека, я бы ожидал, что за него проголосуют такие комментарии, как «показать какой-то код, это не« арендовать кодировщик »». Ничего личного, Томас :) Но я не могу понять, как сообщество решает, что хорошо и что плохо.
目 白 目

4
Эй, не беспокойся. Я предполагаю, что суть вопроса в том, что существует множество способов написания SOAP-клиента с использованием JavaScript. Многие из них безобразны, поэтому я надеялся на некоторые идеи по поддержанию его в чистоте.
Томас Братт

@ dan это потому, что 1. этот вопрос довольно старый, все еще задавалось много фундаментальных вопросов, которые по традиции имеют много откликов, 2. он описывает довольно простую проблему, поэтому он, вероятно, привлекает новых пользователей, которые могут голосовать принцип "эй, я тоже хочу это знать!" вместо «эй, этот вопрос показывает исследовательские усилия. это полезно и понятно!». Поскольку в этом вопросе, на мой взгляд, этого нет, я проголосовал за него. Ничего личного тоже: D
phil294

@ThomasBratt Я, вероятно, продолжу это на мета, но такие вопросы заслуживают шанса. Это идеальный вопрос для справочной библиотеки или базы знаний. Но, может быть, принятый ответ также заслуживает стимула для дополнительной работы? Нет ничего более приемлемого, чем SO, так где еще? Даже ТАК попробовал и поиграл с идеей создания сайта документации - и потерпел неудачу. Ничто не заменит SO ...
YoYo

Ответы:


201

Это самый простой JavaScript SOAP-клиент, который я могу создать.

<html>
<head>
    <title>SOAP JavaScript Client Test</title>
    <script type="text/javascript">
        function soap() {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open('POST', 'https://somesoapurl.com/', true);

            // build SOAP request
            var sr =
                '<?xml version="1.0" encoding="utf-8"?>' +
                '<soapenv:Envelope ' + 
                    'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
                    'xmlns:api="http://127.0.0.1/Integrics/Enswitch/API" ' +
                    'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
                    'xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">' +
                    '<soapenv:Body>' +
                        '<api:some_api_call soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' +
                            '<username xsi:type="xsd:string">login_username</username>' +
                            '<password xsi:type="xsd:string">password</password>' +
                        '</api:some_api_call>' +
                    '</soapenv:Body>' +
                '</soapenv:Envelope>';

            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4) {
                    if (xmlhttp.status == 200) {
                        alert(xmlhttp.responseText);
                        // alert('done. use firebug/console to see network response');
                    }
                }
            }
            // Send the POST request
            xmlhttp.setRequestHeader('Content-Type', 'text/xml');
            xmlhttp.send(sr);
            // send request
            // ...
        }
    </script>
</head>
<body>
    <form name="Demo" action="" method="post">
        <div>
            <input type="button" value="Soap" onclick="soap();" />
        </div>
    </form>
</body>
</html> <!-- typo -->

2
Как насчет отправки <soapenv: Header>? Я попытался встроить теги заголовка в переменную sr, однако сервер получил пустое soapenv: Header
Boiler Bill

Это сработало для меня! (после замены URL-адреса службы SOAP на реальный и отключения междоменных ограничений для моего браузера, как подразумевает @Prestaul)
Нико Беллик,

Я занимаюсь разработкой кроссплатформенного приложения на nativescript для android / ios. Я хочу использовать веб-сервисы SOAP. Пожалуйста, наведите меня на то же самое. Я использовал код выше для запроса SOAP, и я хочу, чтобы формат ответа SOAP, как обрабатывать ответ. Пожалуйста, просмотрите мой вопрос - stackoverflow.com/questions/37745840/…
Онкар Нене

Пришлось использовать это недавно для поддержки устаревшего кода. Обнаружена проблема с отсутствующим заголовком, который приводил к «несоответствию ContractFilter в EndpointDispatcher». Добавление xmlhttp.setRequestHeader('SOAPAction', 'http://myurl.com/action');только перед тем, как xmlhttp.send(sr)исправить это.
RDRick

80

Существует множество особенностей обработки XMLHttpRequest браузерами, этот код JS будет работать во всех браузерах:
https://github.com/ilinsky/xmlhttprequest

Этот код JS преобразует XML в простые в использовании объекты JavaScript:
http://www.terracoder.com/index.php/xml-objectifier

Код JS выше может быть включен на странице, чтобы удовлетворить ваши требования к внешней библиотеке.

var symbol = "MSFT"; 
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "http://www.webservicex.net/stockquote.asmx?op=GetQuote",true);
xmlhttp.onreadystatechange=function() {
 if (xmlhttp.readyState == 4) {
  alert(xmlhttp.responseText);
  // http://www.terracoder.com convert XML to JSON 
  var json = XMLObjectifier.xmlToJSON(xmlhttp.responseXML);
  var result = json.Body[0].GetQuoteResponse[0].GetQuoteResult[0].Text;
  // Result text is escaped XML string, convert string to XML object then convert to JSON object
  json = XMLObjectifier.xmlToJSON(XMLObjectifier.textToXML(result));
  alert(symbol + ' Stock Quote: $' + json.Stock[0].Last[0].Text); 
 }
}
xmlhttp.setRequestHeader("SOAPAction", "http://www.webserviceX.NET/GetQuote");
xmlhttp.setRequestHeader("Content-Type", "text/xml");
var xml = '<?xml version="1.0" encoding="utf-8"?>' +
 '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
                'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
                'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' + 
   '<soap:Body> ' +
     '<GetQuote xmlns="http://www.webserviceX.NET/"> ' +
       '<symbol>' + symbol + '</symbol> ' +
     '</GetQuote> ' +
   '</soap:Body> ' +
 '</soap:Envelope>';
xmlhttp.send(xml);
// ...Include Google and Terracoder JS code here...

Два других варианта:


Что мне делать, если я хочу передать несколько конвертов?
Аджай Патель

Я использую приведенный выше код, но xmlhttp.responseText всегда приводит к тому, что null.can предоставить мне несколько ссылок для устранения ошибки
user969275

Ссылка для удаления кода Google: github.com/ilinsky/xmlhttprequest
ToastyMallows

48

Это невозможно сделать с помощью простого JavaScript, если веб-служба не находится в том же домене, что и ваша страница. Изменить: в 2008 году и в IE <10 это не может быть сделано с прямым JavaScript, если служба находится в том же домене, что и ваша страница.

Если веб-служба находится в другом домене [и вам необходимо поддерживать IE <10], вам придется использовать прокси-страницу в своем собственном домене, которая будет получать результаты и возвращать их вам. Если вам не нужна старая поддержка IE, вам нужно добавить поддержку CORS к вашему сервису. В любом случае вы должны использовать что-то вроде библиотеки, предложенной Тимьятом, потому что вы не хотите анализировать результаты самостоятельно.

Если веб-служба находится в вашем собственном домене, не используйте SOAP. Нет веских причин для этого. Если веб-сервис находится в вашем собственном домене, измените его так, чтобы он мог возвращать JSON и избавил вас от необходимости справляться со всеми трудностями, которые идут с SOAP.

Краткий ответ: не делайте SOAP-запросов из javascript. Используйте веб-сервис для запроса данных из другого домена, и если вы это сделаете, то проанализируйте результаты на стороне сервера и верните их в удобной для js форме.


1
Намерение состоит в том, чтобы сервер SOAP также служил HTML-страницей для простого тестирования и оценки. Клиент будет в том же домене. Похоже, не используется SOAP для внешнего интерфейса. Есть комментарии, почему? Пожалуйста, добавьте в новый вопрос: stackoverflow.com/questions/127038
Томас Братт

1
Нет смысла отвечать там ... Я согласен с Гизмо по всем трем пунктам. XML раздутый и сложный для решения с JS, в то время как JSON является лаконичным и нативным.
Prestaul

10
«не может быть сделано»: сегодня это может быть сделано с (в основном) прямым JavaScript, если клиент поддерживает Cross-Origin Resource Sharing . Надеюсь, через 3-4 года он станет общедоступным.
Константин

2
@Constantin, CORS разрешит это, если вы хотите поддерживать только новые браузеры и если у вас есть контроль над сервером и вы можете добавить поддержку CORS там же. При этом, я все еще буду утверждать, что SOAP-вызовы должны выполняться только между серверами, и клиент должен использовать что-то более дружественное к JS, например JSON.
Prestaul

1
@NikoBellic клиент на основе браузера может использовать XMLHttpRequest, возможно, через такую ​​библиотеку, как jquery. Клиент узла будет использовать что-то еще. Большинство веб-сервисов используют REST в качестве руководства для разработки API, но есть много хороших шаблонов. Ключевым моментом здесь является то, что тела запроса / ответа являются JSON, потому что клиенты JavaScript (браузер / узел / где угодно) понимают JSON изначально.
Prestaul

14

Вы можете использовать плагин jquery.soap, чтобы сделать работу за вас.

Этот скрипт использует $ .ajax для отправки SOAPEnvelope. Он может принимать XML DOM, XML-строку или JSON в качестве входных данных, а ответ может быть возвращен как XML DOM, XML-строка или JSON.

Пример использования с сайта:

$.soap({
    url: 'http://my.server.com/soapservices/',
    method: 'helloWorld',

    data: {
        name: 'Remy Blom',
        msg: 'Hi!'
    },

    success: function (soapResponse) {
        // do stuff with soapResponse
        // if you want to have the response as JSON use soapResponse.toJSON();
        // or soapResponse.toString() to get XML string
        // or soapResponse.toXML() to get XML DOM
    },
    error: function (SOAPResponse) {
        // show error
    }
});

8

Томас:

JSON предпочтительнее для использования на переднем конце, потому что это Javascript. Поэтому у вас нет XML для работы. SOAP это боль без использования библиотеки из-за этого. Кто-то упомянул SOAPClient, которая является хорошей библиотекой, мы начали с нее для нашего проекта. Однако у этого были некоторые ограничения, и мы должны были переписать его большими кусками. Он выпущен как SOAPjs и поддерживает передачу сложных объектов на сервер, а также включает в себя некоторый пример прокси-кода для использования служб из других доменов.


2
«JSON предпочтительнее для внешнего использования, потому что это javascript». - JSON это не JavaScript. (Это просто похоже на JavaScript.)
nnnnnn

2
ru.wikipedia.org/wiki/JSON - Буквально расшифровывается как «нотация объектов JavaScript», и хотя я согласен с тем, что JSON является спецификацией, а не языком и поэтому явно «не javascript», вы должны согласиться с тем, что способ, которым он назван, может легко запутать людей.
П. Роу

8

Кто-нибудь пробовал это? https://github.com/doedje/jquery.soap

Кажется, очень легко реализовать.

Пример:

$.soap({
url: 'http://my.server.com/soapservices/',
method: 'helloWorld',

data: {
    name: 'Remy Blom',
    msg: 'Hi!'
},

success: function (soapResponse) {
    // do stuff with soapResponse
    // if you want to have the response as JSON use soapResponse.toJSON();
    // or soapResponse.toString() to get XML string
    // or soapResponse.toXML() to get XML DOM
},
error: function (SOAPResponse) {
    // show error
}
});

приведет к

<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <helloWorld>
        <name>Remy Blom</name>
        <msg>Hi!</msg>
    </helloWorld>
  </soap:Body>
</soap:Envelope>

4
<html>
 <head>
    <title>Calling Web Service from jQuery</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $("#btnCallWebService").click(function (event) {
                var wsUrl = "http://abc.com/services/soap/server1.php";
                var soapRequest ='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">   <soap:Body> <getQuote xmlns:impl="http://abc.com/services/soap/server1.php">  <symbol>' + $("#txtName").val() + '</symbol>   </getQuote> </soap:Body></soap:Envelope>';
                               alert(soapRequest)
                $.ajax({
                    type: "POST",
                    url: wsUrl,
                    contentType: "text/xml",
                    dataType: "xml",
                    data: soapRequest,
                    success: processSuccess,
                    error: processError
                });

            });
        });

        function processSuccess(data, status, req) { alert('success');
            if (status == "success")
                $("#response").text($(req.responseXML).find("Result").text());

                alert(req.responseXML);
        }

        function processError(data, status, req) {
        alert('err'+data.state);
            //alert(req.responseText + " " + status);
        } 

    </script>
</head>
<body>
    <h3>
        Calling Web Services with jQuery/AJAX
    </h3>
    Enter your name:
    <input id="txtName" type="text" />
    <input id="btnCallWebService" value="Call web service" type="button" />
    <div id="response" ></div>
</body>
</html>

Слушайте лучший учебник JavaScript с SOAP с примером.

http://www.codeproject.com/Articles/12816/JavaScript-SOAP-Client


3

Несколько отличных примеров (и готовый клиент JavaScript SOAP!) Здесь: http://plugins.jquery.com/soap/

Проверьте файл readme и остерегайтесь ограничений браузера того же источника.


3

Легко использовать SOAP Web-сервисы с помощью JavaScript -> Листинг B

function fncAddTwoIntegers(a, b)
{
    varoXmlHttp = new XMLHttpRequest();
    oXmlHttp.open("POST",
 "http://localhost/Develop.NET/Home.Develop.WebServices/SimpleService.asmx'",
 false);
    oXmlHttp.setRequestHeader("Content-Type", "text/xml");
    oXmlHttp.setRequestHeader("SOAPAction", "http://tempuri.org/AddTwoIntegers");
    oXmlHttp.send(" \
<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' \
xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
 xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
  <soap:Body> \
    <AddTwoIntegers xmlns='http://tempuri.org/'> \
      <IntegerOne>" + a + "</IntegerOne> \
      <IntegerTwo>" + b + "</IntegerTwo> \
    </AddTwoIntegers> \
  </soap:Body> \
</soap:Envelope> \
");
    return oXmlHttp.responseXML.selectSingleNode("//AddTwoIntegersResult").text;
}

Это может не соответствовать всем вашим требованиям, но это действительно начало ответа на ваш вопрос. (Я переключил XMLHttpRequest () для ActiveXObject ("MSXML2.XMLHTTP") ).


1

Простейший пример состоит из:

  1. Получение пользовательского ввода.
  2. Составление сообщения XML SOAP, похожего на это

    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <GetInfoByZIP xmlns="http://www.webserviceX.NET">
          <USZip>string</USZip>
        </GetInfoByZIP>
      </soap:Body>
    </soap:Envelope>
  3. Размещение сообщения на URL веб-сервиса с использованием XHR

  4. Синтаксический анализ ответа XML SOAP веб-сервиса

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     <soap:Body>
      <GetInfoByZIPResponse xmlns="http://www.webserviceX.NET">
       <GetInfoByZIPResult>
        <NewDataSet xmlns="">
         <Table>
          <CITY>...</CITY>
          <STATE>...</STATE>
          <ZIP>...</ZIP>
          <AREA_CODE>...</AREA_CODE>
          <TIME_ZONE>...</TIME_ZONE>
         </Table>
        </NewDataSet>
       </GetInfoByZIPResult>
      </GetInfoByZIPResponse>
     </soap:Body>
    </soap:Envelope>
  5. Представление результатов пользователю.

Но это много хлопот без внешних библиотек JavaScript.


9
Не пример Javacript.
Томас Братт

Даже в первой части вы не ответили - будьте функциональны (другими словами, на самом деле работайте).
Шахар Эльдад

0
function SoapQuery(){
  var namespace = "http://tempuri.org/";
  var site = "http://server.com/Service.asmx";
  var xmlhttp = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");
  xmlhttp.setOption(2,  13056 );  /* if use standard proxy */
  var args,fname =  arguments.callee.caller.toString().match(/ ([^\(]+)/)[1]; /*Имя вызвавшей ф-ции*/
  try { args =   arguments.callee.caller.arguments.callee.toString().match(/\(([^\)]+)/)[1].split(",");  
    } catch (e) { args = Array();};
  xmlhttp.open('POST',site,true);  
  var i, ret = "", q = '<?xml version="1.0" encoding="utf-8"?>'+
   '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+
   '<soap:Body><'+fname+ ' xmlns="'+namespace+'">';
  for (i=0;i<args.length;i++) q += "<" + args[i] + ">" + arguments.callee.caller.arguments[i] +  "</" + args[i] + ">";
  q +=   '</'+fname+'></soap:Body></soap:Envelope>';
            // Send the POST request
            xmlhttp.setRequestHeader("MessageType","CALL");
            xmlhttp.setRequestHeader("SOAPAction",namespace + fname);
            xmlhttp.setRequestHeader('Content-Type', 'text/xml');
            //WScript.Echo("Запрос XML:" + q);
            xmlhttp.send(q);
     if  (xmlhttp.waitForResponse(5000)) ret = xmlhttp.responseText;
    return ret;
  };





function GetForm(prefix,post_vars){return SoapQuery();};
function SendOrder2(guid,order,fio,phone,mail){return SoapQuery();};

function SendOrder(guid,post_vars){return SoapQuery();};

0

База данных Angularjs $ http основана на XMLHttpRequest . До тех пор, пока в заголовке содержимого установлен следующий код будет делать.

"Content-Type": "text/xml; charset=utf-8"

Например:

function callSoap(){
var url = "http://www.webservicex.com/stockquote.asmx";
var soapXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://www.webserviceX.NET/\"> "+
         "<soapenv:Header/> "+
         "<soapenv:Body> "+
         "<web:GetQuote> "+
         "<web:symbol></web:symbol> "+
         "</web:GetQuote> "+
         "</soapenv:Body> "+
         "</soapenv:Envelope> ";

    return $http({
          url: url,  
          method: "POST",  
          data: soapXml,  
          headers: {  
              "Content-Type": "text/xml; charset=utf-8"
          }  
      })
      .then(callSoapComplete)
      .catch(function(message){
         return message;
      });

    function callSoapComplete(data, status, headers, config) {
        // Convert to JSON Ojbect from xml
        // var x2js = new X2JS();
        // var str2json = x2js.xml_str2json(data.data);
        // return str2json;
        return data.data;

    }

}

0

Вопрос в том, что является самым простым примером SOAP с использованием Javascript?

Этот ответ является примером в среде Node.js , а не в браузере. (Давайте назовем скрипт soap-node.js) И мы будем использовать общедоступный веб-сервис SOAP из Европы PMC в качестве примера, чтобы получить список ссылок на статью.

const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const DOMParser = require('xmldom').DOMParser;

function parseXml(text) {
    let parser = new DOMParser();
    let xmlDoc = parser.parseFromString(text, "text/xml");
    Array.from(xmlDoc.getElementsByTagName("reference")).forEach(function (item) {
        console.log('Title: ', item.childNodes[3].childNodes[0].nodeValue);
    });

}

function soapRequest(url, payload) {
    let xmlhttp = new XMLHttpRequest();
    xmlhttp.open('POST', url, true);

    // build SOAP request
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4) {
            if (xmlhttp.status == 200) {
                parseXml(xmlhttp.responseText);
            }
        }
    }

    // Send the POST request
    xmlhttp.setRequestHeader('Content-Type', 'text/xml');
    xmlhttp.send(payload);
}

soapRequest('https://www.ebi.ac.uk/europepmc/webservices/soap', 
    `<?xml version="1.0" encoding="UTF-8"?>
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header />
    <S:Body>
        <ns4:getReferences xmlns:ns4="http://webservice.cdb.ebi.ac.uk/"
            xmlns:ns2="http://www.scholix.org"
            xmlns:ns3="https://www.europepmc.org/data">
            <id>C7886</id>
            <source>CTX</source>
            <offSet>0</offSet>
            <pageSize>25</pageSize>
            <email>ukpmc-phase3-wp2b---do-not-reply@europepmc.org</email>
        </ns4:getReferences>
    </S:Body>
    </S:Envelope>`);

Перед запуском кода необходимо установить два пакета:

npm install xmlhttprequest
npm install xmldom

Теперь вы можете запустить код:

node soap-node.js

И вы увидите вывод, как показано ниже:

Title:  Perspective: Sustaining the big-data ecosystem.
Title:  Making proteomics data accessible and reusable: current state of proteomics databases and repositories.
Title:  ProteomeXchange provides globally coordinated proteomics data submission and dissemination.
Title:  Toward effective software solutions for big biology.
Title:  The NIH Big Data to Knowledge (BD2K) initiative.
Title:  Database resources of the National Center for Biotechnology Information.
Title:  Europe PMC: a full-text literature database for the life sciences and platform for innovation.
Title:  Bio-ontologies-fast and furious.
Title:  BioPortal: ontologies and integrated data resources at the click of a mouse.
Title:  PubMed related articles: a probabilistic topic-based model for content similarity.
Title:  High-Impact Articles-Citations, Downloads, and Altmetric Score.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.