Anda di halaman 1dari 54

Communication Protocols and Web Services

Created by Omer Katz, 2010

Omer Katz Some Rights Reserved

Structure of a standard networking


stack for the Web

TCP/IP

Transport Layer

SSL
RPC

Session Layer

HTTP

Presentation +
Application Layer

Network Layer

IPv4
IPv6

Data Link Layer

LLC
MAC

Physical Layer

LAN
MAN

Common serialization formats

JSON

Natively supported within JavaScript


Capable of referencing other records by convention
Human readable format
Lightweight
Easy to parse
Uses JSON-Schema to validate itself
Key-Value based syntax

XML

JavaScript exposes a proprietary DOM API


Human readable format for hierarchal data
Hard to parse
Consumes more memory than JSON
Supports XSLT and XPath
Uses XML-Schema or DTD to validate itself
Markup based syntax

What is a web service?

A web service is typically an application programming interface (API) or Web API that is
accessed via Hypertext Transfer Protocol (HTTP) and executed on a remote system, hosting
the requested service.
Web services do not provide the user with a GUI.
Web services instead share business logic, data and processes through a programmatic
interface across a network.
Developers can then add the Web service to a GUI (such as a Web page or an executable
program) to offer specific functionality to users.

Web services communication protocols


RPC

XML-RPC

JSON-RPC

HTTP Bound
SMD Service Mapping Description

JSONP

Allows cross domain Ajax requests

SOA

SOAP
XML Based
Strongly typed
WSDL dependant

REST
Stateless
Cacheable
Code On Demand
Client and Server are unaware of each others state
Layered System
Uniform Interface
Service may be described through SMD, WSDL, WADL or not at all

What is RPC?

Remote Procedure Call.


Allows to access server-side/inter-process operations from a client through a well-defined
protocol.
Examples: COBRA, XML-RPC, JSON-RPC, DCOM, RMI
Client is tightly coupled with the server

JSON-RPC

Request/Response model

Advantages

Lightweight
JSON-Schemas can be extended to validate specific message
Not bound to HTTP by the specification, but might be used with it
Can be natively serialized from within JavaScript
Service discovery can be achieved through SMD or WADL

Disadvantages

Request
Notification
Response
Error
Batch operations

Procedural
The web service's methods grow linearly with the number of client request types
Not bound to a URI

Conclusion

Fits for low resources environment (embedded devices)


Does not fit for rapidly growing web services
Does not fit for web services operating on many entities unless the web service is an HTTP service

JSON-RPC Examples

A Notification:

{
jsonrpc: 2.0,
m ethod: update,
param s: [1,2,3,4,5]
}

JSON-RPC Examples

A Request
{
jsonrpc: 2.0,
m ethod: subtract,
param s: {
subtrahend: 23,
m inuend: 42
},
id: 3
}

JSON-RPC Examples

An Error:
{
jsonrpc: 2.0,
error: {
code: -32601,
message: Procedure not found.
},
id: 1
}

JSON-RPC Examples

Batch Request:
[
{
jsonrpc: 2.0,
method: sum,
params: [1,2,4],
id: 1
},
{
jsonrpc: 2.0,
method: notify_hello,
params: [7]
},
{
jsonrpc: 2.0,
method: subtract,
params: [42,23],
id: 2
}
]

JSON-RPC Examples

Batch Response:
[
{
jsonrpc:2.0,
result:7,
id:1
},
{
jsonrpc:2.0,
result:19,
id:2
},
{
jsonrpc:2.0,
error:{
code:-32601,
message:Procedurenotfound.
},
id:5
},
]

XML-RPC

Request/Response model

Advantages

Bound to a URI
Can represent hierarchical data in a readable way
XSLT & XPath
Can be validated through XML-Schema or DTD

Disadvantages

Request
Response
Error

Procedural
The web service's methods grow linearly with the number of client request types
Bound to HTTP
Only appropriate for the web
Hard to parse
Heavy payload
Consumes a lot of memory
No bulk operations

Conclusion

Does not fit for rapidly growing web services


Does not fit for embedded devices
Fits to represent hierarchical data

XML-RPC Examples

Request:

< ?xm lversion= 1.0?>


< m ethodCall>
< m ethodN am e> exam ples.getStateN am e< /m ethodN am e>
< param s>
< param >
< value>
< i4> 40< /i4>
< /value>
< /param >
< /param s>
< /m ethodCall>

XML-RPC Examples

Response:

< ?xm lversion= 1.0?>


< m ethodResponse>
< param s>
< param >
< value>
< string> South D akota< /string>
< /value>
< /param >
< /param s>
< /m ethodResponse>

XML-RPC Examples

Error:

< ?xm lversion= 1.0?>


< m ethodResponse>
< fault>
< value>
< struct>
< m em ber> < nam e> faultCode< /nam e>
< value> < int> 4< /int> < /value>
< /m em ber>
< m em ber>
< nam e> faultString< /nam e>
< value> < string> Too m any param eters.< /string> < /value>
< /m em ber>
< /struct>
< /value>
< /fault>
< /m ethodResponse>

What is SOA?

Service Oriented Architecture.


Allows to access server-side from a client through a well-defined protocol.
Examples: SOAP, REST, SOAPjr
Client does not have to be tightly coupled with the server.
Unlike RPC based web services which usually are not discoverable there is a way to discover
services in SOA based web service.

Service Description Standards

WSDL

Web Services Description Language


Well known
Verbose
Uses XML
Not human readable
Used by WCF
Feels natural for SOAP services
Endorsed by Microsoft
WSDL 1.1 supports only GET and POST requests

Service Description Standards - Continued

WADL

Web Application Description Language


Not very well known
A bit less verbose than WSDL
Uses XML
A bit more human readable
Used by Java
Feels natural for REST Services
Endorsed by Sun Microsystems

Service Description Standards - Continued

SMD

Service Mapping Description


Working Draft status
Less verbose
Uses JSON
Human readable
Used by the Dojo Toolkit
Not stable
Endorsed by Sitepen and The Dojo Foundation

WSDL Example

< description>
< types>
< schem a>
< elem ent nam e= m yM ethod>
< com plexType>
< sequence>
< elem ent nam e= x type= xsd:int/>
< elem ent nam e= y type= xsd:fl
oat/>
< /sequence>
< /com plexType>
< /elem ent>
< elem ent nam e= m yM ethodResponse>
< com plexType/>
< /elem ent>
< /schem a>
< /types>

WSDL Example
< m essage nam e= m yM ethodRequest>
< part nam e= param eters elem ent= m yM ethod/>
< /m essage>
< m essage nam e= em pty>
< part nam e= param eters elem ent= m yM ethodResponse/>
< /m essage>
< portType nam e= PT>
< operation nam e= m yM ethod>
< input m essage= m yM ethodRequest/>
< output m essage= em pty/>
< /operation>
< /portType>

Hold your horses, theres more

WSDL Example
< binding interface= ...>
< !-- The binding of a protocolto an interface, sam e structure
as the interface elem ent -->
< /binding>
< service interface= ...>
< !-- D efi
n es the actualaddresses of the bindings, as in 1.1,
but now ports are called endpoints -->
< endpoint binding= ... address= .../>
< /service>
< /description>

And it goes on and on I actually tried to keep it short.

Have I already mentioned that


WSDL is verbose?

SMD Example
{
target:/jsonrpc, // this defines the URL to connect for the services
transport:POST, // We will use POST as the transport
envelope:JSON-RPC-1.2, // We will use JSON-RPC
SMDVersion:2.0,
services: {
add : { // define a service to add two numbers
parameters: [
{name:a,type:number}, // define the two parameters
{name:b,type:number}],
returns:{type:number}
},
foo : { // nothing is required to be defined, all definitions are optional.
//This service has nothing defined so it can take any parameters
//and return any value
},
getNews : {
// we can redefine the target, transport, and envelope for specific services
target: /newsSearch,
transport: GET,
envelope: URL,
parameters:[ { name: query, type: string, optional: false, default: } ],
returns:{type:array}
}
}

But thats not even a standard yet

WADL Example

< application xm lns:xsi= http://w w w .w 3.org/2001/XM LSchem a-instance


xsi:schem aLocation= http://research.sun.com /w adl/2006/10 w adl.xsd
xm lns:xsd= http://w w w .w 3.org/2001/XM LSchem a
xm lns:ex= http://w w w .exam ple.org/types
xm lns= http://research.sun.com /w adl/2006/10>
< gram m ars>
< include href= ticker.xsd/>
< /gram m ars>

WADL Example

< resources base= http://w w w .exam ple.org/services/>


< resource path= getStockQ uote>
< m ethod nam e= G ET>
< request>
< param nam e= sym bolstyle= query type= xsd:string/>
< /request>
< response>
< representation m ediaType= application/xm l
elem ent= ex:quoteResponse/>
< fault status= 400 m ediaType= application/xm l
elem ent= ex:error/>
< /response>
< /m ethod>
< /resource>
< ! m any other U RIs>
< /resources>
< /application>

Looks a bit better, but its not


widely adopted.
So what do we do?

Service Discovery - Summery

Use whatever your platform allows you (WSDL for .NET, WADL for JAVA and SMD for Dojo)
Dont allow service discovery this may happen if:

You intend the web service to be used only internally.


You are not using a tool to generate a proxy.
You intend the web service to always be on a fixed IP

Allow gradual service discovery

Each call will expose different operations that are available


Occasionally adds an unnecessary overhead

Can be solved using a parameter in the request to turn off and on gradual discovery

Only exposes a part of the service that is related to the call

Service Discovery WS-Discovery

Web Services Dynamic Discovery


A multicast discovery protocol that allows to locate web services over local network
Uses web services standards like SOAP

SOAP

Simple Object Access Protocol


Message model:

Advantages:

Type safe
WCF support feels more natural
More appropriate for event driven use cases
Services are discoverable
Can carry any kind of data

Disadvantages:

Request
Response
Error

Verbose
WSDL
Heavy payload, especially over HTTP
Does not fit for streaming
HTTP already knows how to handle requests/responses
Accessing from a non-WCF client is nearly impossible
Uses XML for the envelope, which makes the possibility to send any kind of data pretty much obsolete

Conclusion

Major pain in the ass

SOAP Example
SOAP Request
POST /InStock HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn

<?xml version=1.0?>
<soap:Envelope xmlns:soap=http://www.w3.org/2001/12/soap-envelope
soap:encodingStyle=http://www.w3.org/2001/12/soap-encoding>
<soap:Body xmlns:m=http://www.example.org/stock>

<m:GetStockPrice>

<m:StockName>IBM</m:StockName>

</m:GetStockPrice>
</soap:Body>
</soap:Envelope>

SOAP Example
SOAP Response
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn

<?xml version=1.0?>
<soap:Envelope
xmlns:soap=http://www.w3.org/2001/12/soap-envelope
soap:encodingStyle=http://www.w3.org/2001/12/soap-encoding>
<soap:Body xmlns:m=http://www.example.org/stock>

<m:GetStockPriceResponse>

<m:Price>34.5</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>

Oh dear, take this abomination


away

REST

Representational State Transfer


Constrains

Stateless
Uniform Interface
Layered System
Cacheable
Code On Demand (Optional)

Guiding principles

Identification of resources
Manipulation of resources through these representations
Self-descriptive messages
Hypermedia As The Engine Of Application State (HATEOAS)

REST is an architecture, not a


standard.
This means we relay on whatever
application protocol we have to
use.

REST is not bound to HTTP but


feels natural with HTTP

REST Web Services

A RESTful web service is implemented over HTTP


URI Unique Resource Identifier

Provides unified interface to access resources.

Uses HTTP Verbs

GET

Used to create/replace content

DELETE

Used to update content

PUT

Used to get content, no side effects are guaranteed

POST

/Foos/ - A collection of resources


/Foos/[Identifier]/ - An object instance inside a collection

Used to delete content

OPTIONS
HEAD

Discoverable through OPTIONS and HEAD Verbs


Allows request to refer to different representation through MIME-types
Responds with HTTP Status Codes

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Were going to write a simple blog application


Why ASP.NET MVC?

What are our entities?

Easy to implement
Appropriate for small services
A
A
A
A

Post
Tag
Comment
User

Both tags and comments entities are sub-entities of a post


Both posts and comments entities are sub-entities of a user

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The URI Scheme:

To represent a resource collection of posts: /Posts/


To represent a specific post resource: /Posts/[id]/
To represent a resource collection of comments of a specific post resource: /Posts/[id]/Comments/
To represent a specific comment resource of a specific post resource: /Posts/[id]/Comments/[commentId]
Well, you got the idea, right?

How to implement:

Go to your Global.asax file


Define the routes
Use constrains to avoid routes clashes
Use constrains to define allowed HTTP Verbs

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Implementing the URI Scheme:

public static void RegisterRoutes(RouteCollection routes)


{
//
routes.M apRoute(D eleteCom m ent, Com m ents/{com m entId}/,
new { controller = Com m ents, action = D elete },
new { com m entId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(D ELETE) });
routes.M apRoute(EditCom m ent, Com m ents/{com m entId}/,
new { controller = Com m ents, action = Edit },
new { com m entId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(PU T) });
routes.M apRoute(AddPostCom m ent, Posts/{postId}/Com m ents/,
new { controller = Com m ents, action = Add },
new { postId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(PO ST) });
routes.M apRoute(PostCom m ent, Posts/{postId}/Com m ents/{com m entId}/,
new { controller = Com m ents, action = PostCom m ent },
new { postId = @ \d+ , com m entId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(G ET) });
routes.M apRoute(PostCom m ents, Posts/{postId}/Com m ents/,
new { controller = Com m ents, action = PostCom m ents },
new { postId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(G ET) });
routes.M apRoute(Com m ent, Com m ents/{com m entId},
new { controller = Com m ents, action = Com m ent },
new { com m entId = @ \d+ , httpM ethod = new H ttpM ethodConstraint(G ET) });
routes.M apRoute(U serCom m ents, U sers/{user}/Com m ents/,
new { controller = Com m ents, action = U serCom m ents },
new { user = @ ^ [a-zA-Z0-9_]*$, httpM ethod = new H ttpM ethodConstraint(G ET) });
routes.M apRoute(U serCom m ent, U sers/{user}/Com m ents/{com m entId}/,
new { controller = Com m ents, action = U serCom m ent },

new { user = @ ^ [a-zA-Z0-9_]*$, httpM ethod = new H ttpM ethodConstraint(G ET) });
//
}

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The URI Scheme - Explained:

public static void RegisterRoutes(RouteCollection routes)


{
//
routes.M apRoute(D eleteCom m ent,Com m ents/{com m entId}/,
new { controller = Com m ents,action = D elete },
new { com m entId = @ \d+ ,httpM ethod = new H ttpM ethodConstraint(D ELETE) });
//
}

Defines a route that maps to an action that allows to delete a comment


commentId is limited to integral values (for more information, read about Regular
Expressions)
You can reach to this action only by a DELETE request

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The URI Scheme - Explained:

public static void RegisterRoutes(RouteCollection routes)


{
//
routes.M apRoute(EditCom m ent,Com m ents/{com m entId}/,
new { controller = Com m ents,action = Edit },
new { com m entId = @ \d+ ,httpM ethod = new H ttpM ethodConstraint(PU T) });
//
}

Defines a route that maps to an action that allows to edit a comment


commentId is limited to integral values
You can reach to this action only by a PUT request
Why are we using PUT instead of POST?

The Comments/{commentId}/ URI refers to a specific item in a collection, since we are not sending only
what is updated in our request we prefer to replace the resource instead of updating it

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The URI Scheme - Explained:

public static void RegisterRoutes(RouteCollection routes)


{
//
routes.M apRoute(AddPostCom m ent,Posts/{postId}/Com m ents/,
new { controller = Com m ents,action = Add },
new { postId = @ \d+ ,httpM ethod = new H ttpM ethodConstraint(PO ST) });
//
}

Defines a route that maps to an action that allows to add a comment to a post
postId is limited to integral values
You can reach to this action only by a POST request
Why are we using POST instead of PUT?

The Posts/{postId}/Comments/ URI refers to a collection, PUT will replace all of our existing comments
with a new one
POST only updates a resource, so a new comment is added to our existing comments collection

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The URI Scheme - Explained:

public static void RegisterRoutes(RouteCollection routes)


{
//
routes.M apRoute(PostCom m ent,Posts/{postId}/Com m ents/{com m entId}/,
new { controller = Com m ents,action = PostCom m ent },
new { postId = @ \d+ ,com m entId = @ \d+ ,httpM ethod = new H ttpM ethodConstraint(G ET) });
//
}

Those are the routes we are familiar with, the ones that use GET requests and most of the
time return HTML
In this example, this route maps to an action that allows us to access a specific comment on a
post

Hands On A Simple RESTful Web


Service using ASP.NET MVC

The comments controller:

Now that our routes are defined we know what actions we need to implement
All actions should use valid HTTP Status Codes
All actions must be able to represent themselves in different formats (JSON, XML, HTML, RSS etc.)

How to implement:

Create a new controller called CommentsController


Follow your routing scheme and create the needed actions
Create a new action result decorator that allows you to select the HTTP Status code
Use attributes to define allowed content types and HTTP Verbs

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Implementing the comments controller:

public class Com m entsController : Controller


{
//
[AcceptVerbs(H ttpVerbs.D elete)] // O r [H ttpD elete] if you are using M VC 2 and above
public ActionResult D elete(int com m entId)
{
// D elete operation occurs here
return new H ttpResponseCodeActionResultD ecorator(204); // 204 N o content
}
[AcceptVerbs(H ttpVerbs.Post)] // O r [H ttpPost] if you are using M VC 2 and above
public ActionResult Add(int postId)
{
// Create a new com m ent that belongs to a post w ith a post Id of postId
return Json(new {Com m entId = new Com m entId}) ;
}
[AcceptVerbs(H ttpVerbs.Put)] // O r [H ttpPut] if you are using M VC 2 and above
public ActionResult Add(int com m entId)
{
// Create a new com m ent that belongs to a post w ith a post Id of postId
return new H ttpResponseCodeActionResultD ecorator(201,Json(new {Com m entId = new Com m entId}) ); // 201 - Created
}
//
}

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Implementing the HttpResponseCodeActionResultDecorator:

public class H ttpResponseCodeActionResultD ecorator : ActionResult


{
private readonly int statusCode;
private readonly ActionResult actionResult;
public H ttpResponseCodeActionResultD ecorator(int statusCode)
{
this.statusCode = statusCode;
}
public H ttpResponseCodeActionResultD ecorator(int statusCode, ActionResult actionResult)
: this(statusCode)
{
this.actionResult = actionResult;
}
public override void ExecuteResult(ControllerContext context)
{
context.H ttpContext.Response.StatusCode = statusCode;
if (actionResult != null)
actionResult.ExecuteResult(context);
}
}

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Resources with multiple representations:

Our list of posts should be representable through RSS and Atom feeds but also display them as HTML.
An HTTP request containing an Accept header with a value other than application/rss+xml,
application/atom+xml, text/html or application/xhtml+xml will return the HTTP response code 406 Not
Acceptable.
The implementation is not trivial
An example of an implementation can be seen here: http://
aleembawany.com/2009/03/27/aspnet-mvc-create-easy-rest-api-with-json-and-xml however it does not
conform to HTTP due to the fact that it will either return 404 or the default view.

How to implement:

Create an ActionResult class that inspects the requests Accept header and executes the requested
ActionResult or return 406 Not Acceptable

Hands On A Simple RESTful Web


Service using ASP.NET MVC

Implementing the AcceptTypeResult:

public class AcceptTypeResult : ActionResult


{
private readonly int? successStatusCode;
private readonly object result;
public AcceptTypeResult(object result)
{
this.result = result;
}
public AcceptTypeResult(int successStatusCode, object result)
: this(result)
{
this.successStatusCode = successStatusCode;
}
public override void ExecuteResult(ControllerContext context)
{
var request = context.H ttpContext.Request;
context.H ttpContext.Response.StatusCode = successStatusCode ?? 200;
if (request. AcceptTypes.Contains(application/rss+ xm l))
Rss(result).ExecuteResult(context);
else if (request. AcceptTypes.Contains(application/atom + xm l))
Atom (result).ExecuteResult(context);
else if (request. AcceptTypes.Contains(application/xhtm l+ xm l) || request.AcceptTypes.Contains(text/htm l))
View (result).ExecuteResult(context);
else
context.H ttpContext.Response.StatusCode = 406;
}
}

Bibliography

http://www.infoq.com/articles/webber-rest-workflow
http://www.infoq.com/articles/mark-baker-hypermedia
http://barelyenough.org/blog/2007/05/hypermedia-as-the-engine-of-application-state /
http://third-bit.com/blog/archives/1746.html
http://www.learnxpress.com/create-restful-wcf-service-api-step-by-step-guide.html
http://www.infoq.com/articles/rest-soap-when-to-use-each
http://www.prescod.net/rest/
http://www.prescod.net/rest/rest_vs_soap_overview /
http://www.devx.com/DevX/Article/8155
http://tomayko.com/writings/rest-to-my-wife
http://en.wikipedia.org/wiki/Representational_State_Transfer
http://en.wikipedia.org/wiki/HATEOAS
http://en.wikipedia.org/wiki/SOAP
http://en.wikipedia.org/wiki/SOA
http://en.wikipedia.org/wiki/Web_Application_Description_Language
http://en.wikipedia.org/wiki/WSDL
http://en.wikipedia.org/wiki/JSON-RPC
http://en.wikipedia.org/wiki/XML-RPC
http://www.sitepen.com/blog/2008/03/19/pluggable-web-services-with-smd /

For further reading

http://jcalcote.wordpress.com/2009/08/10/restful-authentication/
http://jcalcote.wordpress.com/2009/08/06/restful-transactions/
http://www.artima.com/lejava/articles/why_put_and_delete.html
http://www.markbaker.ca/2002/08/HowContainersWork/
http://www.w3.org/Protocols/rfc2616/rfc2616.html
http://www.elharo.com/blog/software-development/web-development/2005/12/08/post-vs-put/
http://blog.whatfettle.com/2006/08/14/so-which-crud-operation-is-http-post/
http://cafe.elharo.com/web/why-rest-failed/
http://en.wikipedia.org/wiki/Windows_Communication_Foundation

Thank you for listening!