Understanding Web Services with real world examples.
Go to http://www.webservicex.net/
Name some Web Services available.
Go to the Stock Quote service.
What is the endpoint of this service ?
Go to the endpoint if the Stock Quote service.
How many operation are managed by this service ?
There is a single operation managed by the service, actually the GetQuote
operation.
Check the operation in the WSDL service description.
<?xml version="1.0" encoding="utf-8"?> <wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.webserviceX.NET/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.webserviceX.NET/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> <wsdl:types> <s:schema elementFormDefault="qualified" targetNamespace="http://www.webserviceX.NET/"> <s:element name="GetQuote"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="symbol" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="GetQuoteResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="GetQuoteResult" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="string" nillable="true" type="s:string" /> </s:schema> </wsdl:types> <wsdl:message name="GetQuoteSoapIn"> <wsdl:part name="parameters" element="tns:GetQuote" /> </wsdl:message> <wsdl:message name="GetQuoteSoapOut"> <wsdl:part name="parameters" element="tns:GetQuoteResponse" /> </wsdl:message> <wsdl:message name="GetQuoteHttpGetIn"> <wsdl:part name="symbol" type="s:string" /> </wsdl:message> <wsdl:message name="GetQuoteHttpGetOut"> <wsdl:part name="Body" element="tns:string" /> </wsdl:message> <wsdl:message name="GetQuoteHttpPostIn"> <wsdl:part name="symbol" type="s:string" /> </wsdl:message> <wsdl:message name="GetQuoteHttpPostOut"> <wsdl:part name="Body" element="tns:string" /> </wsdl:message> <wsdl:portType name="StockQuoteSoap"> <wsdl:operation name="GetQuote"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation> <wsdl:input message="tns:GetQuoteSoapIn" /> <wsdl:output message="tns:GetQuoteSoapOut" /> </wsdl:operation> </wsdl:portType> <wsdl:portType name="StockQuoteHttpGet"> <wsdl:operation name="GetQuote"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation> <wsdl:input message="tns:GetQuoteHttpGetIn" /> <wsdl:output message="tns:GetQuoteHttpGetOut" /> </wsdl:operation> </wsdl:portType> <wsdl:portType name="StockQuoteHttpPost"> <wsdl:operation name="GetQuote"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation> <wsdl:input message="tns:GetQuoteHttpPostIn" /> <wsdl:output message="tns:GetQuoteHttpPostOut" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="StockQuoteSoap" type="tns:StockQuoteSoap"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="GetQuote"> <soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" /> <wsdl:input> <soap:body use="literal" /> </wsdl:input> <wsdl:output> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="StockQuoteSoap12" type="tns:StockQuoteSoap"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="GetQuote"> <soap12:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" /> <wsdl:input> <soap12:body use="literal" /> </wsdl:input> <wsdl:output> <soap12:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="StockQuoteHttpGet" type="tns:StockQuoteHttpGet"> <http:binding verb="GET" /> <wsdl:operation name="GetQuote"> <http:operation location="/GetQuote" /> <wsdl:input> <http:urlEncoded /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="StockQuoteHttpPost" type="tns:StockQuoteHttpPost"> <http:binding verb="POST" /> <wsdl:operation name="GetQuote"> <http:operation location="/GetQuote" /> <wsdl:input> <mime:content type="application/x-www-form-urlencoded" /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="StockQuote"> <wsdl:port name="StockQuoteSoap" binding="tns:StockQuoteSoap"> <soap:address location="http://www.webservicex.net/stockquote.asmx" /> </wsdl:port> <wsdl:port name="StockQuoteSoap12" binding="tns:StockQuoteSoap12"> <soap12:address location="http://www.webservicex.net/stockquote.asmx" /> </wsdl:port> <wsdl:port name="StockQuoteHttpGet" binding="tns:StockQuoteHttpGet"> <http:address location="http://www.webservicex.net/stockquote.asmx" /> </wsdl:port> <wsdl:port name="StockQuoteHttpPost" binding="tns:StockQuoteHttpPost"> <http:address location="http://www.webservicex.net/stockquote.asmx" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
What are the available access method to this operation ?
This is defined in the <wsdl:binding>
elements :
Do we have the same information when we examine the
elements within the wsdl:service
element ?
No, we can only see that 4 accesses are available :
Go to the GetQuote operation interface. Type "IBM" as symbol input. Check the XML result.
How is the content of the <string>
element, XML or text content ?
It's text content, not XML although it looks like : all the content is escaped. However the entire string could be parsed to get a standalone XML document.
Explain why after submitting the previous form
we didn't get a <soap:Envelope
?
(displaying the HTML source of the form will help)
By editing the HTML source :
<form action='http://www.webservicex.net/stockquote.asmx/GetQuote' method="POST"> <input type="text" size="50" name="symbol"> <input type="submit" value="Invoke" class="button"> </form>
...we can see that the HTTP request that will be forged by the form will look like :
POST /stockquote.asmx/GetQuote HTTP/1.1 Host: www.webservicex.net Content-Type: application/x-www-form-urlencoded Content-Length: 10 symbol=IBM
...which is bound to the HTTP POST binding :
<wsdl:binding name="StockQuoteHttpPost" type="tns:StockQuoteHttpPost"> <http:binding verb="POST"/> <wsdl:operation name="GetQuote"> <http:operation location="/GetQuote"/> <wsdl:input> <mime:content type="application/x-www-form-urlencoded"/> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body"/> </wsdl:output> </wsdl:operation> </wsdl:binding>
...that states that the payload is in the Body
element, which is defined in the response message
as a tns:string
:
<wsdl:message name="GetQuoteHttpPostOut"> <wsdl:part xmlns:tns="http://www.webserviceX.NET" name="Body" element="tns:string"/> </wsdl:message>
...where this type is defined as an xsd:string
<xsd:schema elementFormDefault="qualified" targetNamespace="http://www.webserviceX.NET/"> ... <xsd:element name="string" nillable="true" type="xsd:string"/>
(rewritten here for convenience)
Forge a SOAP query and submit it with telnet
$ telnet www.webservicex.net 80 Trying 173.201.44.188... Connected to webservicex.net. Escape character is '^]'. POST /stockquote.asmx HTTP/1.1 Host: www.webservicex.net Content-Type: text/xml; charset=utf-8 Content-Length: 260 SOAPAction: "http://www.webserviceX.NET/GetQuote" <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetQuote xmlns="http://www.webserviceX.NET/"> <symbol>IBM</symbol> </GetQuote> </soap:Body> </soap:Envelope>
Result :
HTTP/1.1 200 OK Cache-Control: private, max-age=0 Content-Length: 997 Content-Type: text/xml; charset=utf-8 Server: Microsoft-IIS/7.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Sun, 09 Dec 2012 22:15:25 GMT <?xml version="1.0" encoding="utf-8"?> <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> <GetQuoteResponse xmlns="http://www.webserviceX.NET/"> <GetQuoteResult><StockQuotes> <Stock> <Symbol>IBM</Symbol> <Last>191.95</Last> <Date>12/7/2012</Date> <Time>4:00pm</Time> <Change>+2.25</Change> <Open>190.14</Open> <High>192.20</High> <Low>190.11</Low> <Volume>4091940</Volume> <MktCap>216.9B</MktCap> <PreviousClose>189.70</PreviousClose> <PercentageChange>+1.19%</PercentageChange> <AnnRange>177.35 - 211.79</AnnRange> <Earns>13.913</Earns> <P-E>13.63</P-E> <Name>International Bus</Name> </Stock> </StockQuotes> </GetQuoteResult> </GetQuoteResponse> </soap:Body> </soap:Envelope>
Got a HTTP/1.1 400 Bad Request
with
a body like this ?
<BODY><h2>Bad Request - Invalid Verb</h2> <hr><p>HTTP Error 400. The request verb is invalid.</p> </BODY>
This will occur if the Content-Length: 260
is wrong ; increase the value and fill the end of the
request with then necessary blanks.