Какой самый простой пример SOAP с использованием Javascript?
Чтобы быть максимально полезным, ответ должен:
У меня вопрос: если бы я увидел этот вопрос как первый человек, я бы ожидал, что он будет отвергнут с комментариями типа «покажи код, это не« аренда кодировщика »». Ничего личного, Томас :) Но я не могу понять, как сообщество решает, что хорошо, а что плохо.
Эй, не беспокойся. Думаю, суть вопроса в том, что есть много способов написать клиент SOAP с использованием JavaScript. Многие из них уродливы, поэтому я надеялся, что у меня появятся идеи, как содержать их в чистоте.
@dan это потому, что 1. этот вопрос довольно старый, все еще было задано много фундаментальных вопросов, которые по традиции имеют много положительных голосов, 2. он описывает довольно простую проблему, поэтому он, вероятно, имеет тенденцию привлекать новых пользователей, которые могли бы проголосовать принцип "эй, я тоже хочу это знать!" вместо «эй, этот вопрос показывает исследовательские усилия. он полезен и понятен!». Поскольку, на мой взгляд, в вопросе этого нет, я проголосовал против. Ничего личного тоже: D
@ThomasBratt Я, вероятно, продолжу это на мете, но такие вопросы заслуживают шанса. Это идеальный вопрос для нисходящей справочной библиотеки или базы знаний. Но может быть, принятый ответ также заслуживает стимула к лишней работе? Все еще нет ничего более приемлемого, чем ТАК, так где же еще? Даже SO пыталась и играла с идеей создания сайта документации - и потерпела неудачу. Заменить нечем ТАК ...



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Самый простой пример будет состоять из:
Составление сообщения 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>
Отправка сообщения на URL-адрес веб-службы с использованием XHR
Разбор 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>
Представление результатов пользователю.
Но без внешних библиотек JavaScript возникает много проблем.
Даже в первой части, на которую вы не ответили - будьте функциональны (другими словами, действительно работайте).
Это невозможно сделать с помощью обычного JavaScript, если веб-служба не находится в том же домене, что и ваша страница. Обновлено: в 2008 году и в IE <10 это невозможно сделать с помощью обычного javascript, если только служба не находится в том же домене, что и ваша страница.
Если веб-служба находится в другом домене [и вы должны поддерживать IE <10], вам придется использовать прокси-страницу в вашем собственном домене, которая будет получать результаты и возвращать их вам. Если вам не нужна поддержка старого IE, вам нужно добавить поддержку CORS в свой сервис. В любом случае вам следует использовать что-то вроде библиотеки, предложенной timyates, потому что вы не хотите, чтобы вам приходилось анализировать результаты самостоятельно.
Если веб-служба находится в вашем собственном домене, не используйте SOAP. Для этого нет веских причин. Если веб-служба находится в вашем собственном домене, измените ее так, чтобы она могла возвращать JSON и избавить себя от проблем, связанных со всеми проблемами, связанными с SOAP.
Короткий ответ: не делайте SOAP-запросы из javascript. Используйте веб-службу для запроса данных из другого домена, и если вы это сделаете, проанализируйте результаты на стороне сервера и верните их в удобной для js форме.
Предполагается, что сервер SOAP также будет обслуживать HTML-страницу для простого тестирования и оценки. Клиент будет в том же домене. Не использовать SOAP для внешнего интерфейса, по-видимому, является принятой точкой зрения. Любые комментарии относительно того, почему? Пожалуйста, добавьте в новый вопрос: stackoverflow.com/questions/127038
Нет смысла там отвечать ... Я согласен с Гизмо по всем трем пунктам. XML раздувается, и его сложно обрабатывать с помощью js, в то время как JSON является кратким и родным.
re «невозможно сделать»: сегодня это можно сделать (в основном) с помощью прямого JavaScript, если клиент поддерживает Совместное использование ресурсов между источниками. Надеюсь, что через 3-4 года он станет общедоступным.
@Constantin, CORS разрешит это, если вы готовы поддерживать только новые браузеры, и если у вас есть контроль над сервером и вы можете добавить туда поддержку CORS. При этом я все же буду утверждать, что вызовы SOAP должны выполняться только между серверами, а клиент должен использовать что-то более дружественное к JS, например JSON.
Отличный совет! Какой протокол должен использовать клиент JS для разговора с сервером (для получения JSON)? Если не мыло, то это RESTful? Он по-прежнему использует объект XMLHttpRequest () на стороне клиента?
@NikoBellic клиент на основе браузера может использовать XMLHttpRequest, вероятно, через библиотеку, такую как jquery. Клиент узла будет использовать что-то еще. Большинство веб-сервисов используют REST в качестве руководства для разработки своего API, но есть много хороших шаблонов. Ключевым моментом здесь является то, что тела запроса / ответа представляют собой JSON, потому что клиенты javascript (браузер / узел / где угодно) изначально понимают JSON.
-1, так как это не отвечает на вопрос. Как насчет варианта использования стороннего приложения в вашем домене, которое вы не можете «изменить для возврата JSON»?
@ToastyMallows, за абзац перед этой цитатой я ответил на ваш вопрос, сказав, что сторонние API должны быть проксированы через ваш собственный API. SOAP сложен и раздут и вызывает междоменные проблемы. Лучше создать свой собственный спокойный api, который вызывает прокси.
Томас:
JSON предпочтительнее для внешнего использования, потому что у нас есть простой поиск. Следовательно, вам не нужно иметь дело с XML. Из-за этого SOAP - это боль без использования библиотеки. Кто-то упомянул SOAPClient, хорошую библиотеку, с которой мы начали свой проект. Однако у него были некоторые ограничения, и нам пришлось переписать его большие куски. Он был выпущен как SOAPjs и поддерживает передачу сложных объектов на сервер и включает в себя некоторый образец прокси-кода для использования служб из других доменов.
"JSON предпочтительнее для внешнего использования, потому что это javascript" Удалите это, он распространяет ложную информацию: timelessrepo.com/json-isnt-a-javascript-subset
В том, как браузеры обрабатывают 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...
Два других варианта:
Клиент SOAP JavaScript:
http://www.guru4.net/articoli/javascript-soap-client/en/
Создать JavaScript из WSDL:
https://cwiki.apache.org/confluence/display/CXF20DOC/WSDL+to+Javascript
что мне делать, если я хочу передать несколько конвертов?
Я использую приведенный выше код, но xmlhttp.responseText всегда имеет значение null. можете ли вы предоставить мне ссылки для преодоления ошибки
Ссылка на удаление кода Google: github.com/ilinsky/xmlhttprequest
Легко использовать веб-службы SOAP с помощью 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»)).
Это простейший клиент SOAP на JavaScript, который я могу создать.
<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 -->
А как насчет отправки <soapenv: Header>? Я попытался встроить свои теги заголовков в переменную sr, однако сервер получил пустой soapenv: Header
Это сработало для меня! (после замены 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) исправило это.
<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
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();};
Вы можете использовать плагин jquery.soap, чтобы сделать работу за вас.
This script uses $.ajax to send a SOAPEnvelope. It can take XML DOM, XML string or JSON as input and the response can be returned as either XML DOM, XML string or JSON too.
Пример использования с сайта:
$.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
}
});
Вот несколько отличных примеров (и готовый клиент JavaScript SOAP!): http://plugins.jquery.com/soap/
Проверьте readme и остерегайтесь ограничений браузера того же происхождения.
Кто-нибудь пробовал это? 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>
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;
}
}
Возникает вопрос: «Какой самый простой пример 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.info('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>[email protected]</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.
У меня это сработало, но лично я предпочитаю использовать аксиомы. let xlms = "<? xml version =" 1.0 "encoding =" UTF-8 "?> <S: Envelope xmlns: S =" schemas.xmlsoap.org/soap/envelope "> <S: Header /> <S: Body> ... </ S : Body> </ S: Envelope> "axios .post ('ebi.ac.uk/europepmc/webservices/soap', xmls, {headers: {'Content-Type': 'text / xml'}}) .then (res => {console.info (res );}) .catch (err => {console.info (err);});
Простота и ясность могут противоречить неиспользованию внешней библиотеки. Вы действительно хотите написать свой собственный конвертер классов WSDL -> JS?