Basic Guide to SOAP protocol (II)

Source: Internet
Author: User
X ML as a better way to express network data (NDR)

HTTP is a very useful RPC protocol that supports most of IIOP or DCOM functions in terms of frame groups, connection management, and serialization of object applications. (And URLs is incredibly close to iors and objrefs ). What HTTP lacks is to express parameters in an RPC call in a single standard format. This is where XML is used.

Like NDR And CDR, XML is a platform-independent neutral data expression protocol. XML allows data to be serialized into a form that can be passed, making it easy to be decoded on any platform. XML has the following characteristics different from NDR And CDR:

A large number of XML encoding and decoding software exist in each programming environment and the XML on the platform is text-based. It is quite easy to use a low-tech programming environment to process XML in a particularly flexible format, it is easy to be extended in a consistent way to support scalability. in XML, each element and attribute has a domain URI associated with it, which is specified by the xmlns attribute.

Consider the following XML document:

<Reverse_string xmlns = "urn: Schemas-develop-com: stringprocs">
<String1> Hello, world </string1>
<Comment xmlns = 'HTTP: // foo.com/documentation'>
This is a comment !!
</Comment>
</Reverse_string>

The URI of the element <reverse_string> and <string1> is urn: Schemas-develop-com: stringprocs. The name URI of the <comment> element is http://foo.com/documentation. The fact that the second URI is also a URL is not important. In both cases, Uris are simply used to eliminate the ambiguity between elements <reverse_string>, <string1>, <comment>, and any other elements that happen to have the same name.

For convenience, XML allows the domain name URIs to be mapped to a unique local prefix. This means that the following XML documents are semantically equivalent to the above documents:

<SP: reverse_string
Xmlns: sp = "urn: Schemas-develop-com: stringprocs"
Xmlns: Doc = 'HTTP: // foo.com/documentation'
>
<SP: string1> Hello, world </SP: string1>
<DOC: Comment>
This is a comment !!
</DOC: Comment>
</SP: reverse_string>

The subsequent form is easier for the author, especially if there are many domain names in use.

XML also supports data expression with types. The XML Schema Specification being introduced standardizes a vocabulary set for describing XML data types. The following describes the XML schema of an element <reverse_string>:

<Schema
Xmlns = 'HTTP: // www.w3.org/5o/xmlschema'
Targetnamespace = 'urn: Schemas-develop-com: stringprocs'
>
<Element name = 'reverse _ string'>
<Type>
<Element name = 'string1' type = 'string'/>
<Any minoccurs = '0' maxoccurs = '*'/>
</Type>
</Element>
</Schema>

This XML schema definition illustrates the XML Name Domain urn: Schemas-develop-com: stringprocs contains an element named <reverse_string>, this element contains a child element named string1 (type: string), which is observed by 0 or more unspecified elements.

The XML Schema Specification also defines a set of built-in primitive data types and a mechanism for creating element types in an XML document. The following XML document uses the XML schema type attribute to link elements with the type name:

<Customer
Xmlns = 'HTTP: // customer.is.king.com'
Xmlns: XSD = 'HTTP: // www.w3.org/5o/xmlschema'
>
<Name XSD: TYPE = 'string'> don box </Name>
<Age XSD: TYPE = 'float'> 23.5 </Name>
</Customer>

A new mechanism connecting XML document cases to XML Schema description is being standardized during the writing of this article.

HTTP + xml = soap

Soap uses XMLCodeIt is converted into request and Response Parameter encoding mode and transmitted over HTTP. This seems a bit abstract. Specifically, a soap method can be viewed as an HTTP request and response following the soap encoding rules. A soap terminal can be seen as an HTTP-based URL used to identify the target of a method call. Similar to CORBA/IIOP, soap does not need to bind a specific object to a given terminal, but is implementedProgramTo determine how to map an object terminal identifier to an object on the server.

A soap request is an http post request. The Content-Type of the SOAP request must use text/XML. And it must contain a request-Uri. The server explains how this request-Uri is related to the implementation, but many implementations may use it to map to a class or an object. A soap request must also use the soapmethodname HTTP header to specify the method to be called. To put it simply, the soapmethodname header is the application-related method name specified by the URI. It uses the # character as the separator to separate the method name from the URI:

Soapmethodname: urn: strings-com: istring # reverse

This header indicates that the method name is reverse and the range URI is urn: strings-com: istring. In soap, the name domain URI that specifies the method name range is functionally equivalent to the interface ID that specifies the method name range in DCOM or IIOP.

Simply put, the HTTP body of a SOAP request is an XML document that contains the values of the [in] and [In, out] parameters in the method. These values are encoded as sub-elements of a significant calling element, which has the method name and Name Domain uri of the soapmethodname HTTP header. The Calling element must appear in the standard soap <envelope> and <body> elements (these two elements will be discussed later ). The following is a simple soap Method Request:

Post/string_server/object17 HTTP/1.1
HOST: 209.110.197.2
Content-Type: text/XML
Content-Length: 152
Soapmethodname: urn: strings-com: istring # reverse
<Envelope>
<Body>
<M: reverse xmlns: M = 'urn: strings-com: istring'>
<Thestring> Hello, world </thestring>
</M: reverse>
</Body>
</Envelope>

The soapmethodname header must match the first child element in <body>; otherwise, the call is rejected. This allows the firewall administrator to effectively filter calls to a specific method without parsing XML.

The soap response format is similar to the request format. The response body contains the [out] and [In, out] parameters of the method. This method is encoded as a sub-element of a significant response element. The element name is the same as the name of the requested call element, but is connected with the response suffix. Below is the soap response to the previous SOAP request:

200 OK
Content-Type: text/XML
Content-Length: 162
<Envelope>
<Body>
<M: reverseresponse xmlns: M = 'urn: strings-com: istring'>
<Result> dlrow, olleh </result>
</M: reverseresponse>
</Body>
</Envelope>

The response element is named reverseresponse, which is the method name followed by the response suffix. Note that there is no soapmethodname HTTP header. This header is only required in the request message and not in the Response Message.

Many new users of soap are confused that there is no requirement in soap about how the SOAP server uses the request header to distribute requests. This is left as an implementation detail. Some Soap servers map the request-Uris to the class name and dispatch the calls to static methods or to instances of classes that are active in the request duration. Other soap servers map request-Uris to always-alive objects. They often use query strings to encode an object keyword used to locate the server process. Some other soap servers use HTTP cookies to encode an object keyword. This keyword can be used to restore the object state in each method request. The important thing is that the customer does not know the differences. The customer software simply follows the HTTP and XML rules to form a SOAP request, allowing the server to freely serve the request in the way it deems the most appropriate.

Core of the soap body

The XML feature of soap is to serialize data-type instances into XML encoding modes. For this purpose, soap does not require traditional RPC-style proxies. Instead, a soap method call contains at least two data types: request and response. Consider the following com IDL code:

[UUID (DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA)]
Interface ibank: iunknown {
Hresult withdraw ([in] Long account,
[Out] float * newbalance,
[In, out] float * Amount
[Out, retval] variant_bool * overdrawn );
}

Under any RPC protocol, the value of the account and amount parameters will appear in the request message, the value of the newbalance, overdrawn parameter, and the updated value of the amount parameter will appear in the Response Message.

Soap improves method requests and method responses to the first-class status. In soap, requests and responses are actually type instances. To understand a method such as ibank: How does withdraw map a SOAP request and response type, consider the following data types:

Struct withdraw {
Long account;
Float amount;
};

All request parameters are packaged into a single data type. The following data indicates packaging all response parameters to a single data type.

Struct withdrawresponse {
Float newbalance;
Float amount;
Variant_bool overdrawn;
};

The following simple visual basic program is provided, which uses the previously defined ibank interface:

Dim bank as ibank
Dim amount as single
Dim newbal as single
Dim overdrawn as Boolean
Amount = 100
Set bank = GetObject ("Soap: http://bofsoap.com/am ")
Overdrawn = Bank. Withdraw (3512, amount, newbal)

You can imagine that the underlying proxy (possibly a soap, DCOM, or IIOP proxy) looks as shown in figure 8. Here, before sending a request message, the parameter is serialized as a request object. Response objects received by the same response message are deserialized as parameters. A similar change also occurs on the called server.

When a method is called through soap, the request object and response object are serialized into a known format. Each soap body is an XML document with a significant root element called <envelope>. The tag name <envelope> is composed of the soap Uri (URN: Schemas-xmlsoap-org: soap. v1) to define the scope. All soap-specific elements and attributes are defined by this URI. SOAP envelope contains an optional

<Soap: Envelope
Xmlns: Soap = 'urn: Schemas-xmlsoap-org: Soap. V1 '>
<Soap: Body>
<Ibank: withdraw xmlns: ibank =
'Urn: UUID: DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA '>
<Account> 3512 </account>
<Amount> 100 </amount>
</Ibank: withdraw>
</Soap: Body>
</Soap: envelope>

The following response message is encoded:

<Soap: Envelope
Xmlns: Soap = 'urn: Schemas-xmlsoap-org: Soap. V1 '>
<Soap: Body>
<Ibank: withdrawresponse xmlns: ibank =
'Urn: UUID: DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA '>
<Newbalance> 0 </newbalance>
<Amount> 5 </amount>
<Overdrawn> true </overdrawn>
</Ibank: withdrawresponse>
</Soap: Body>
</Soap: envelope>

Note that the [In, out] parameter appears in two messages.

After checking the format of the request and response object, you may have noticed that the serialization format is usually:

<T: typename xmlns: t = 'namespaceuri '>;
<Fieldname1> field1value </fieldname1>
<Fieldname2> field2value </fieldname2>
</T: typename>

In the case of a request, the type is an implicit C-style structure, which consists of the [in] and [In, out] parameters in the corresponding method. For the response, the type is also an implicit C-style structure, which consists of the [out] and [In, out] parameters in the corresponding method. This style of each field corresponds to a sub-element is sometimes called the formal element format (ENF ). Generally, soap uses only the XML feature to convey comments describing the information contained in the element content.

Like DCOM and IIOP, soap supports protocol header extensions. Soap uses an optional

Struct causality {
Uuid id;
};

In this case, if the uri of the Header element cannot be identified, the Header element can be safely ignored.

However, you cannot safely ignore header elements in all soap bodies. If a specific SOAP header is critical for correct message processing, the Header element can be marked as required by the soap attribute mustunderstand = 'true. This attribute tells the recipient that the Header element must be identified and processed to ensure correct use. To force the preceding causality header to become a required header, the message will be written as follows:

<Soap: Envelope
Xmlns: Soap = 'urn: Schemas-xmlsoap-org: Soap. V1 '>
<Soap: Header>
<Causality
Soap: mustunderstand = 'true'
Xmlns = "http://comstuff.com">
<ID> 362099cc-aa46-bae2-5110-99aac9823bff </ID>
</Causality>
</Soap: Header>
<! -Soap: Body element elided for clarity->
</Soap: envelope>

When the soap software encounters a situation where it cannot identify a required Header element, it must reject the message and present an error. If the server finds an unrecognized Header element in a SOAP request, it must return an error response without sending any calls to the target object. If the client finds a required Header element that cannot be identified in a SOAP request, it must return a runtime error to the caller. (In the case of COM, this will map to an obvious hresult ).

Soap Data Type

In a SOAP message, each element may be a soap structure element, a root element, an access element, or an independent element. In soap, soap: envelope, soap: Body, and soap: header are three unique structural elements. Their basic relationships are described in the following XML Schema:

<Schema targetnamespace = 'urn: Schemas-xmlsoap-org: Soap. V1 '>
<Element name = 'envelope '>
<Type>
<Element name = 'header' type = 'header'
Minoccurs = '0'/>
<Element name = 'body' type = 'body'
Minoccurs = '1'/>
</Type>
</Element>
</Schema>

Among the four types of soap elements, all except the structure elements are used as expression type instances or references to a type instance.

The root element is a significant element. It is a direct sub-element of soap: body or soap: header. Soap: the body has only one root element, which expresses the call, response, or error object. This root element must be the first child element of the soap: body. Its Tag Name and domain name URI must correspond to the HTTP soapmethodname header or the soap: Fault in case of an error message. Soap: The Header element has multiple root elements, and each header extension associated with the message corresponds to one. These root elements must be the direct sub-elements of the soap: header. Their tag names and domain Uris indicate the types of extended data.

An access element is used as a domain, attribute, or data member of the expression type. A given type of domain has only one access element in its soap expression. The access element tag name corresponds to the type domain name. Consider the following Java class definitions:

Package com. bofsoap. ibank;
Public class adjustment {
Public int account;
Public float amount;
}

The serialized instance in a SOAP message is as follows:

<T: Adjustment
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank '>
<Account> 3514 </account>
<Amount> 100.0 </amount>
</T: adjustment>

In this example, the access element account and amount are called simple access elements because they access the elements that correspond to the W3C XML Schema Specification (see http://www.w3.org/TR/XMLSchema-2) the value of the original data type defined in Part 2. This specification specifies the names and expressions of data types such as string, value, and date, and uses the <datatype> structure in a new schema definition to define the mechanism of the New primitive type.

For access elements that reference simple types, the element values are simply encoded as character data directly under the access element, as shown above. There are two technologies to encode the access elements of the reference combination type (that is, the access elements constructed by sub-access elements. The simplest way is to embed a structured value directly under an access element. Consider the following Java class definition:

Package com. bofsoap. ibank;
Public class transfer {
Public adjustment from;
Public adjustment;
}

If an embedded value is used to encode the access element, a serialized transfer object in soap is as follows:

<T: Transfer
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank'
>
<From>
<Account> 3514 </account>
<Amount>-1, 100.0 </amount>
</From>
<To>
<Account> 3518 </account>
<Amount> 100.0 </amount>
</To>
</T: Transfer>

In this case, the value of the adjustment object is directly encoded under their access element.

When considering the combination of access elements, several issues need to be explained. Consider the above transfer class first. The from and to fields of the class are object references, which may be null. Soap uses the null attribute of XML Schemas to indicate null values or references. The following example shows a serialized transfer object whose from field is empty:

<T: Transfer
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank'
Xmlns: XSD = 'HTTP: // www.w3.org/5o/xmlschema/instance'
>
<From XSD: null = 'true'/>
<To>
<Account> 3518 </account>
<Amount> 100.0 </amount>
</To>
</T: Transfer>

If the property does not exist, the implicit value of XSD: NULL is false. Whether the attribute of a given element can be null is controlled by the XML schema definition. For example, the following XML Schema only allows the from access element to be null:

<Type name = 'transferer'>
<Element
Name = 'from'
Type = 'adjustment'
Nullable = 'true'
/>
<Element
Name = 'to'
Type = 'adjustment'
Nullable = 'false' <! -False is the default->
/>
</Type>

Without the nullable attribute in the schema declaration of an element, it means that the element in an XML document cannot be empty. The exact format of the null access element is still being revised. For more information, see the latest SOAP specification.

Another problem related to the access element is the substitution caused by the type relationship. Because the previous adjustment class is not a final class, it is possible that the from and to fields of the transfer object actually reference an instance of the inheritance type. To support this type-compatible replacement, soap uses an XML schema convention for the Type attribute specified by the domain name.

The value of this type attribute is a name that limits the specific type of the element. Consider the following adjustment extension class:

Package com. bofsoap. ibank;
Public class auditedadjustment extends adjustment {
Public int auditlevel;
}

The following Java language is provided:

Transfer xfer = new transfer ();
Xfer. From = new auditedadjustment ();
Xfer. From. Account = 3514; xfer. From. Amount =-100;
Xfer. From. auditlevel = 3;
Xfer. To = new adjustment ();
Xfer. to. Account = 3518; xfer. From. Amount = 100;

The serialization form of the transfer object in soap is as follows:

<T: Transfer
Xmlns: XSD = 'HTTP: // www.w3.org/5o/xmlschema'
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank'
>
<From XSD: TYPE ='t: auditedadjustment '>
<Account> 3514 </account>
<Amount>-1, 100.0 </amount>
<Auditlevel> 3 </auditlevel>
</From>
<To>
<Account> 3518 </account>
<Amount> 100.0 </amount>
</To>
</T: Transfer>

Here, the XSD: Type attribute references a type name defined by the domain name, which can be used by deserialization programs to instantiate the correct type of the object. Because the to access element references an instance of the expected type (rather than an alternative inheritance type), The XSD: Type attribute is not required.

The transfer class just avoided a key issue. What happens if the serialized transfer object is initialized in the following way:

Transfer xfer = new transfer ();
Xfer. From = new adjustment ();
Xfer. From. Account = 3514; xfer. From. Amount =-100;
Xfer. To = xfer. From;

Based on previous discussions, the serialization form of transfer objects in soap is as follows:

<T: Transfer
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank '>
<From>
<Account> 3514 </account>
<Amount>-1, 100.0 </amount>
</From>
<To>
<Account> 3514 </account>
<Amount>-1, 100.0 </amount>
</To>
</T: Transfer>

This expression has two problems. The first easy to understand problem is that the same information is sent twice, which leads to a larger message than the actually needed message. A more subtle but important problem is that the deserialization program cannot distinguish two adjustment objects with the same value from a single adjustment object referenced in two places, the identity relationship between the two access elements is lost. If the message recipient has executed the following test on the result object, (xfer. To = xfer. From) no true is returned.

Void processtransfer (Transfer xfer ){
If (xfer. To = xfer. From)
Handledoubleadjustment (xfer. );
Else
Handleadjustments (xfer. To, xfer. From );
}

(Xfer. to. Equals (xfer. From) The fact that true is returned only compares the values of two access elements, not their identities.
To support serialization of types that must maintain identity relationships, soap supports multi-reference access elements. Currently, the access element we access is a single-reference access element. That is to say, the element value is embedded under the access element, in addition, other access elements are allowed to reference that value (similar to the [unique] concept in NDR ). The multi-reference access element is always encoded as an empty element that contains only known soap: href attributes. Soap: The href attribute always contains a code snippet identifier, which corresponds to the instance referenced by the access element. If the to and from access elements have been encoded as multi-reference access elements, the serialized transfer object is as follows:

<T: Transfer
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank '>
<From soap: href = '# id1'/>
<To soap: href = '# id1'/>
</T: Transfer>

This encoding assumes that an instance of the Type compatible with the adjustment class has been serialized elsewhere in envelope, and the instance has been marked with the soap: Id attribute, as shown below:

<T: adjustment soap: Id = 'id1'
Xmlns: t = 'urn: develop-com: Java: COM. bofsoap. ibank '>
<Account> 3514 </account>
<Amount>-1, 100.0 </amount>
</T: adjustment>

For multi-reference access elements, decomposing the code segment identifier (for example, # id1) into the correct instance is the work of the deserialization program.

The previous discussion explains how a multi-reference access element is associated with its target instance. The following describes where the target instance is serialized. This is related to the concept of independent elements and packages.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.