Web Disservices: Microsoft's Misstep
by Mark Pilgrim
|
Pages: 1, 2
An alternate approach
First, let me say that I have no problem with the actual data that Microsoft is returning from these web services calls. XML is a fine way of serializing complex data structures, and several of Microsoft's public web services methods return data structures much more complex than a single string. The WSDL file contains an XML schema that defines these data structures and datatypes and allows WSDL-aware tools to produce wrapper classes to translate these serializations into native data structures.
So +1 on XML, +1 on WSDL, +1 on XML Schemas. These are all good things, have sizable benefits, and are worth their cost in complexity. I am also in favor of HTTP, which is a fine way of requesting data and receiving responses, even XML responses. It's well understood, widely supported, and mature. +1 on HTTP.
But let's think about how we could provide the same set of services as Microsoft has offered but in such a way that we take advantage of the Web more directly. First, Microsoft is overloading a single URL, choosing to dispatch their methods on a custom HTTP header (SOAPAction). This method name could be put into the URL instead:
http://ws.microsoft.com/mscomservice/GetVersion
http://ws.microsoft.com/mscomservice/GetCultures
http://ws.microsoft.com/mscomservice/GetTopDownloads
And so forth. This would accomplish the same thing, but it would make logging more useful, since a standard IIS or Apache access log would contain the method name.
Second, those method arguments... None of these methods seem to take complex data structures; the most complex datatype they take is a GUID, which is simply a long string in a particular format. And as you can see from the sample requests, the server does not require declaring the datatype of each argument on each request; both the client and server are deemed to know them from the schema within the WSDL file. Each parameter is named and order doesn't matter. So, basically, we have a bunch of unordered, named key-value pairs that we're passing to a URL. So instead of
<soap:Body>
<GetTopDownloads xmlns="http://www.microsoft.com">
<topType>Recent</topType>
<topN>25</topN>
<cultureID>en-US</cultureID>
</GetTopDownloads>
</soap:Body>
why not
http://ws.microsoft.com/mscomservice/GetTopDownloads?topType=Recent&topN=25&cultureID=en-US
Third, let's consider that insecure approach to authentication. It is susceptible to a number of attack types, and it requires both client and server to store sensitive information in plain text. It is not widely implemented in toolkits. There is also no programmatic way for a client to determine what authentication mechanism the server requires; it is documented in human-readable form, of course, but there is no way to write a generic client that speaks to this and to other web services without specific knowledge of each.
It appears to have been chosen solely as a way to show off a new standard which Microsoft had a hand in creating. I would replace it altogether HTTP digest authentication, which is more mature. Not only does digest authentication solve several security problems, it's more widely supported, and there is a standard, documented way for the server to announce that digest authentication is required (if a client tries to call a web services method without the proper credentials or without any credentials at all).
Given all this, what would our web service look like? Well, taking the GetVersion example above and making the necessary modifications, it would look like this:
Host: ws.microsoft.com
GET /mscomservice/GetVersion HTTP/1.0
Content-type: text/xml
Authorization: Digest Username="DEVELOPERTOKEN", realm="Microsoft.com web services", nonce="NONCE", uri="/mscomservice/GetVersion", qop="auth", nc="00000001", cnonce="CNONCE", response="RESPONSE", opaque="OPAQUE"
(The developer token is the same as the original example, and the other values are generated from the Microsoft-supplied PIN and other constants defined in RFC 2617.)
And the response would look like this:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<GetVersionResult xmlns="http://www.microsoft.com">Microsoft.Com Platform Services 1.0 Beta</GetVersionResult>
Note that this approach accomplishes exactly the same thing: we are calling a method with no parameters, getting a string back, and identifying ourselves appropriately to the server, just like Microsoft's SOAP service. The differences are where things go:
The method name is now part of the URL instead of being in a custom HTTP header and in the
<soap:Body>. This makes logging more useful.The method arguments are now query parameters in the URL instead of being stored as elements within the
<soap:Body>.The authentication information is now transmitted in the standard
AuthorizationHTTP header used by digest authentication.
|
Related Reading
|
There are further subtle benefits. If you look closely you'll see we're using GET instead of POST. This opens up all kinds of possibilities for controlled caching, both server-side and client-side. For example, if I call GetVersion the server could return an Etag or Last-Modified HTTP header along with the response. The next time I call GetVersion, I could pass along this etag, and if the data hasn't changed, the web services server could simply return an HTTP status code 304 "Not Modified" rather than returning the same response over and over. This is an ordinary and clever part of the Web.
Ah, but I know what you're thinking. You're thinking "well, I don't care about what goes over the wire because I'll never see it. I'll just point my Web-Services-Enabled IDE to a WSDL file and call a method in a wrapper class that takes no arguments and returns a string." Okay, you can still do that. WSDL supports HTTP GET bindings, so you could create a WSDL file that described this URL-and-query-parameters web service, just as easily as you can describe an everything-in-the-SOAP-envelope web service. Here is such a WSDL file. Try it in Microsoft's Visual Studio .NET; you'll find that it generates wrappers for the methods and classes with native data structures, which are virtually identical to the wrapper classes generated by Microsoft's original WSDL file. (In fact they're slightly simpler because there's slightly less cruft in the serialized XML responses. Other than that, they're identical.)
Microsoft wouldn't do this, but you should
Realistically, would Microsoft consider doing this? No, probably not. As you can see, the hypothetical version is much simpler over the wire, so there is some benefit from reduced bandwidth. But for developers using Microsoft tools (i.e. Microsoft's primary customers here), there is no other benefit since WSDL hides the complexities of either approach equally well. Everything is simple when you have perfect tools, and Microsoft makes a lot of money selling those tools. Microsoft has implemented its web services in as complex a manner as possible, and then it proceeds to sell developer tools that make calling those web services trivially easy.
However, you should consider the second approach, assuming you're trying to make money from your actual web services instead of from selling developer tools. The primary advantage of the second approach is that it is significantly easier to use when you don't have perfect tools -- in this case, that means non-Microsoft tools that haven't caught up to Microsoft's latest standards yet. Digest authentication is more widely supported than the UsernameToken scheme Microsoft is using; it's more secure and more extensible too. Query strings are easier to produce than SOAP bodies; even if you have a good SOAP library, they're still easier to debug. Developers win with reduced debugging costs, and everybody wins with reduced bandwidth costs.
Further reading: I've put together a live Microsoft.com Web Services gateway that acts as a proxy between Microsoft.com's SOAP-based web services and a hypothetical second approach similar to what I've described here. Live, clickable web services calls are provided; the gateway script takes the URL-and-query-parameters and translates them into the SOAP body that Microsoft's server requires, and sends it along, then takes the response and strips out all unnecessary SOAP envelope and returns just the XML the client needs. Sample client code is available to call the gateway from both C# and Python, along with a WSDL file, and the gateway script itself.
Share your experience in our forums.
(* You must be a member of XML.com to use this feature.)
Comment on this Article
| Titles Only | Titles Only | Newest First |
- Los Angeles Locksmith Safe & Vault Sales and Installation 24/7 Locksmiths 1-877-364-5264
2008-12-19 11:04:12 services123 [Reply]
Los Angeles Locksmith Safe & Vault Sales and Installation 24/7 Locksmiths 1-877-364-5264
San Fernando Valley Locksmith 1-818-386-1022
Los Angeles Hollywood Locksmith 1-323-678-2704
West Los Angeles, Marina Del Rey, Culver City, Santa Monica, Beverly Hills Locksmith 1-310-925-1720 For All Your Home & Business Needs Doors installation wood, metal, Kalamein, and fire rated wood doors for both heavyweight commercial and standard residential needs. Door Closers Panic Bars Fire Exit Devices Floor or Head Check Bolts Door Frames Hinges Buzzer Systems Card Access Elevator Doors magnetic door locks, electric strikes, CCTV install Dvr Video Camera master key systems, CCTV and video surveillance, Alarm Systems, Keyless Entry Systems and Access Control Iron Works specializes in custom exterior and interior wrought iron design. We design and hand forge wrought iron entrance gates, driveway gates Child guard gates A/C cage gates Elevator doors Backyard gates Fire exit gates Custom design gates Storefront and Commercial Rolling
Los Angeles Locksmith, locksmith, lock smith, locks, keys, service, door, set, security, los angeles locksmith, auto, car, home, office, door lock, open, install, repair, professional, locksmiths, unlock, lockout, locked out, rekey, rekeying, change lock, usa, california, los angeles, santa monica locksmith, marina del rey locksmith, santa clarita locksmith, hollywood locksmith, beverly hills locksmith, sherman oaks locksmith, encino locksmith, burbank locksmith, agoura hills locksmith, 411 locksmith, yellow pages locksmith, mobile, Commercial locksmith, Residential locksmith, Locksmiths, professional, Locksmith 30 MIN RESPONSE EMERGENCY .Commercial locksmith, Residential locksmith ,Automotive locksmith, Emergency Locked out Locksmith rekeying locks installatin, Roadside Assistance
- AA Locksmiths Services Los Angeles 1-818-386-1022
2008-09-24 18:38:12 0 [Reply]
AAA Locksmith in Los Angeles 1- 818-386-1022
Los Angeles Locksmith provides fast, reliable, professional 24 Hour Emergency Locksmith services at extremely competitive rates.
We Install New Locks Unlock Autos, Homes doors locks, and Businesseslocks installation
Get reimbursed for lockouts if you have roadside assistance
We Rekey locks for Homes and Businesses doors locks
- Clarifications
2003-10-23 17:28:26 David Byrden [Reply]
I'm not sure that we all realise just what Microsoft are doing here. This service is not an end in itself; it's a demo of Web Services in general. Many of the suggested changes would break its compliance with Web Services standards and defeat its purpose.
Or did we mean to criticize the web services standards themselves? In that case, many of the suggested changes are moot because they are HTTP-specific. There's no point in suggesting that
web services become "more like the Web itself": they don't want to be. They are not committed to HTTP protocol, and they do not follow the REST architecture.
I will now try to evaluate the suggestions on those terms.
Putting each method at a different URL with a meaningful name: valid.
Using stronger authentication: valid.
Using HTTP digest authentication: won't work outside the Web AFAIK.
Using GET: won't work outside the Web.
URL-encoding the parameters: won't scale.
And one more thing: I don't think SOAP is trying to "sell development environments", because the message displayed in the article was feasible for a lone C programmer with a sockets library to generate and send. (Parsing the reply would require an XML parser.)
As a practical example, I just booted up the Java SDK and WSDP (total cost: zero). I fed the URL of Microsoft's WSDL to this Sun tool, and it generated a bunch of Java classes without a complaint. Adding the PIN to outgoing messages may take 12 lines of code.
David
- Simplicity Is The Way
2003-10-03 14:45:55 Kimanzi Mati [Reply]
I have long been a believer of simplicity being the best way to do things. The large number of specifications being churned out for XML and web services are staggering. The unfortunate effect of this prolification of specifications is that it has bred complexity. This complexity dissuades many developers from using web services to the degree they could/should be.
Part of my work has been to address this issue at Emergent Logic LLC. We have a web services development platform called Superx++ Markup Engine (SuperxME) that is basically REST (and XML through and through). We use URLs, as you showed very elegantly in your article, as the means by which the web services are invoked. The web services are implemented in Superx++, an XML-based object oriented programming language, but it is also possible to integrate other languages as well. In short, there is flexibility provided in simplicity.
In all, the best way forward for IT is to minimize complexity. The complexity only breeds confusion, which may also lead to insecurity, which has plagued many companies. I am glad you wrote your article for this reason: you have showed quite plainly how a simpler and more elegant solution will work better!
Keep it up,
Kimanzi Mati
President and CEO
Emergent Logic LLC
http://www.emergentlogic.com
- Where can I get more documentation?
2003-09-26 04:34:42 Joe Dias [Reply]
I really liked this article, so I was wondering where can I get more documentation, case studies, tutorials, on this "way of doing web services" ?
Thanks.
- Of Course
2003-09-25 16:35:48 Lucas Fletcher [Reply]
Maybe now it is finally becoming transparently clear to all that SOAP et al. is a scam to sell development environments. I'm sure there were devs at MS that made the same points you did, but were told on high to eat the dogfood.
- Will it scale?
2003-09-25 07:35:04 j d [Reply]
I like your ideia, and it makes perfect sense for this particular case. But..
will it scale?
Would it be able to handle complex datatypes and binary data? And long method invocation strings? Aren't URIs limited in the number os chars they can have?
- Will it scale?
2003-09-26 03:04:20 Brian Ewins [Reply]
"Would it be able to handle complex datatypes and binary data?"
This reminds me of the old chestnut of someone asking "What's the Gaelic for spaghetti?" only to get the reply "What's the English for spaghetti?". SOAP handles complex data types and binary as text representations - Mark's REST version of the service would encode the complex data types and binary as, erm, text representations...
"And long method invocation strings? Aren't URIs limited in the number os chars they can have?"
The limit isn't one you'd run into in normal circumstances. You are thinking of the old days when CGI was converted into arguments on the command line for a script.
Another more pertinent argument is, queries generally don't need to scale up that much (GET requests = queries) - I'll cite the "html web" as evidence of this. Obviously, in these cases, the authors have achieved something that is cacheable and addressable by designing within the restrictions of an URL.
An implication of that statement is that, by using SOAP+POST for queries, the authors reason is one or more of:
a) working on a "minority case" problem
b) deliberately disabling caching
c) deliberately disabling addressability
d) other restrictions (toolset, management, other devs) made SOAP+POST more practical
e) unaware of the issues
f) just following the herd
g) too lazy to actually design the service
NB There are fine, valid reasons in that list, and I only got to the "namecalling" ones when I ran out of ones by which the author could /justify the choice/ of SOAP+POST over a GET based service.
- Will it scale?
2003-10-23 15:16:55 David Byrden [Reply]
>> Mark's REST version of the service would encode
>> the complex data types and binary as, erm, text
>> representations.
In what format? URL-encoded XML? How easy will that be to edit by hand, since editors for URL-encoded XML are not thick on the ground?
On the programming side, putting the output of an XML serializer through an URL encoder would not be difficult; just pointless.
Sorry, but having data in an URL instead of XML makes sense only when the data format is trivially simple.
David
- Will it scale?
- Will it scale?
- Great article!
2003-09-24 23:14:40 Bertrand Delacrétaz [Reply]
Thanks Mark, your no-nonsense approach shows how things should be. Why make simple things complicated...
- Method in the URI
2003-09-24 20:05:25 Mark Baker [Reply]
Nice! But I think you're missing one very important advantage of putting the "method in the URI"; that the client doesn't have to know what that method means in order to get the data. In fact, you could remove the method entirely, e.g.
http://ws.microsoft.com/mscomservice/version
Or even
http://ws.microsoft.com/j098jf8fja98fjawe98rj
- Amen!
2003-09-24 19:07:26 Seth Ladd [Reply]
Thanks for showing that you really, REALLY need to use 12 different standards and a $1000 IDE to get some text over HTTP, that you can do it with slightly less complexity.
I'm not going to go into the whole REST vs RPC thing. I will mention that when you are designing a solution, please remember that YAGNI (You Ain't Gonna Need It). If you're just trying to shuttle some text around HTTP, just use HTTP. You might not even need XML!
Sometimes, the giant WS stack (whatever that is) is just too much. Don't get caught in the hype!
