6 ms·
If you have REST, why use XML-RPC?
- nicpottier 17y agoKeep fighting the good fight, XML-RPC needs to die.
- jhherren 17y agoThe first answer that comes to mind is tooling. At one extreme you have SOAP, where your IDE can make complete proxy objects from a WSDL file. At the other end is REST, where normally you're in luck if there's a nice client library to translate request/response into objects, but otherwise you're left with API documentation. (Is anyone really using WADL?) Somewhere in between is XML-RPC, where you're more than likely to find some kind of reflection method to call such as client.get_methods or something similar.
- johns 17y agoI'm going to take this opportunity to shamelessly plug an open source project I've started for easily turning requests/responses into .NET objects: http://restsharp.org http://restsharp.org
- ramen 17y agoThere is a de-facto standard for that: system.listMethods to list supported methods, system.methodSignature to get the parameter and return types for a method, and system.methodHelp to get its documentation. It's not an ideal solution, since method signatures are shallow and not every server implements these methods the same way (or at all), but they are enough to do basic code generation for statically-typed languages. Here's an example of that for OCaml: http://code.google.com/p/xmlrpc-light/source/browse/trunk/examples/genclient/genclient.ml http://code.google.com/p/xmlrpc-light/source/browse/trunk/ex...
- mscantland 17y agoBut our clients use XML-RPC Touché. Client: But your design is in Latin, which I don't speak... Engineer: Yes, but Twitter is written in Latin... Client: You're fired. Client needs as an afterthought are why engineers are considered by most to be professionals, while programmers are considered fodder for outsourcing to low-wage countries.
- generalk 17y agoJust in case there's some confusion: that's exactly my point. Not the part about engineers vs. programmers, but the "client needs trump personal preference" bit. In our case, in order to be players in the industry, we have to support XML-RPC/SOAP. (edit: typos)
- ramen 17y agoI like how XML-RPC support is built into Python. If a server supports XML-RPC, I can get an instant command-line interface that feels like using an ordinary library. The data structures that XML-RPC supports are mostly the same as JSON: arrays, hashes, integers, floats, and strings. There are also date/time values, which are automatically deserialized as Python datetime objects, and binary values which are transparently base64-encoded. Being able to use native types is a plus over dealing with XML trees. The lack of object types, in contrast with SOAP, is a feature in my opinion, since it keeps the interface portable across many languages. XML-RPC uses XML and HTTP, but it hides both from the programmer. I think it is a mistake to criticize XML-RPC for not integrating deeply with HTTP, because HTTP is not really the point of XML-RPC. It's just an implementation detail. It happens that HTTP and XML libraries are everywhere, so XML-RPC lets you tunnel a simple RPC protocol through an infrastructure that is common across many programming languages. Every REST interface I have tried to integrate with uses HTTP error codes differently, treats the GET/POST/PUT/DELETE commands in its own peculiar way, and has unique requirements for authentication. I am not at all sure that deep HTTP integration is appropriate for APIs. Regardless of the protocol (or "architectural style", if you insist), documentation of data structures, calling conventions, and error codes is essential, and just saying "we use HTTP" is insufficient to communicate these details. Disclaimer: I wrote the xmlrpc-light library for OCaml. http://code.google.com/p/xmlrpc-light/ http://code.google.com/p/xmlrpc-light/
- generalk 17y agoEvery REST interface I have tried to integrate with uses HTTP error codes differently, treats the GET/POST/PUT/DELETE commands in its own peculiar way, and has unique requirements for authentication. I can't defend systems that (for example) misuse HTTP status codes or ignore HTTP authentication, but this puts it at the same level as XML-RPC, which re-invents error codes, methods, and authentication every time. documentation of data structures, calling conventions, and error codes is essential, and just saying "we use HTTP" is insufficient to communicate these details. I absolutely agree. Documentation is essential for a web service, regardless of how you provide that service.
- ramen 17y ago
- billpg 17y agoSOAP an its ilk seem the easiest solution at first glance. Say I've got a server that can blat a frobnitz, what could be simpler than supplying a pair of functions? int[] GetBlattableFrobnitzIDs(); void BlatFrobnitz(int frobnitzId); Two functions that just magically appear when you point your IDE at a server and tell it to automatically generate a proxy class. Simple! What's the REST alternative? Getting the list of IDs is okay, but how do you give a "blat" instruction? Until you've experienced REST in anger, its not obvious what you need to do. Go beyond superficial uses and REST shines, but a beginner used to calling library functions might not see it.
- jonknee 17y agoI loathe SOAP, but it may just be because Python doesn't support it well. In your example it seems like the obvious thing would be to make a POST request to /blat-frobnitz.
- conover 17y agohttps://fedorahosted.org/suds/ https://fedorahosted.org/suds/ Suds is the only decent Python module for SOAP that I've seen. I've never been able to get ZSI or others to work very well.
- jonknee 17y agoAgreed, but I ran into some issues with Suds the last time I used it and ended up having to make a patch. I'm not familiar enough with either Suds or SOAP to know who's fault it was, but the whole experience still took way too long. I'm sure it's great stuff if you're on Java or .NET and have an IDE do all the magic for you, but SOAP is really ugly from the outside.
- Nwallins 17y agoI would put the frobnitz ID into the blat queue: PUT http://my-fake-server.com/blat_q/2452352 http://my-fake-server.com/blat_q/2452352
- jerf 17y agoPython 2.4.3 (#1,...) Type "help", "copyright", "credits" or "license" for more information. >>> import xmlrpclib >>> server = xmlrpclib.ServerProxy("http://www.something.invalid/xmlrpc") >>> server.namespace.function(True, ["A", "B"], {"q": [1, 2, 3]}) {'A': 8, 'B': ['hello', 8]} "REST" can't match that. "REST + some other stuff I layer on top" can, but you have to bring more to the party; for instance, you can decide that everything will be JSON coming back, but you had to decide that, so you had to do the work. On the other hand as is so often the case with this increased responsibility you get more power; XML-RPC has no decent binary capabilities, for instance, which is easy with REST. That doesn't mean the work isn't worthwhile. My personal feeling is that if XML-RPC meets your needs, you should probably use it, but if it doesn't, don't hesitate to move on. RPC is a crazy and cruel world, though; here there be dragons. REST is better than starting from scratch in most ways but you can still end up down the rabbit hole surprisingly quickly. For instance, REST tempts you into considering caching in a layer designed for caching human document accesses; this may or may not actually have the semantics you are interested in and it can get subtle.
- ramen 17y agoCaching has been the main reason I have chosen REST over XML-RPC in certain instances - the ability to use existing web proxy and caching solutions to cache an API is certainly convenient. However, I completely agree about your last sentence here. Cache invalidation is tricky, since there isn't a standard HTTP method to tell a web cache to forget something it has cached. Also, client-side caching at a higher level using something like memcached has worked demonstrably better for me in many instances, and it offers more fine-tuned control over lifetime and expiration.
- generalk 17y agoI'm confused about your Python example and how REST can't achieve that. bash$ curl http://my-fake-service.com/people/1.json {name: "John Doe", address: "123 Fake St"} I think opposite you, however. My feeling is that REST will probably meet your needs, and if for some reason you're required to use XML-RPC, then use that. It all depends on your starting point and biases.
- sern 17y agoIt's more work to write a client library for XML-RPC/SOAP, but a single one of those libraries is likely to work with any such service you encounter. Most users never have to write one themselves. On the other hand, it's easy to write an HTTP "REST" client library. But it seems that everyone has a different idea of what REST is. Amazon's implementation of REST isn't even close to the generally-accepted definition, for instance. Indeed, you need (to write) a separate client module for every service you use, and that's where REST fails. Because it's so easy to write a REST service, it seems more like REST is an excuse for lazy server writers to get by.
- fragmede 17y agobut now we're discussing specific implementations, which is a separate issue. The author states that specific implementations is a separate issue, but it really isn't. You can't ignore that a good implementation will mean that people will actually use your pet mechanism over someone else's. Most people don't want to reinvent the wheel, so they're not going to be writing the lib to handle the wire protocol, they're going to use a library that does what they need. REST is heavy, and XML-RPC unnecessarily so. Facebook's Thrift (http://incubator.apache.org/thrift/ http://incubator.apache.org/thrift/ ) is a lightweight alternative to both. (That said, REST in Python is fairly easy - http://developer.yahoo.com/python/python-rest.html http://developer.yahoo.com/python/python-rest.html )
- tjpick 17y ago"Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml." I have a very hard time believing that is a lightweight alternative to anything. For REST all you need is an http library.
- fragmede 17y agoAh. The on-wire protocol is what is lightweight. The framework certainly isn't. For simple REST via an http library, how many bytes actually have be encoded before you send it, and be decoded at the other end? (Keeping mind that Thrift originated at Facebook may make the overhead from REST seem more relevant.)
- WilliamLP 17y agoXML-RPC is just what it says, a protocol for calling remote functions, isn't it? It gives you a unified means to specify functions, along with parameters and their types, and gives errors when the requests don't match the definition. With a REST implementation you roll yourself, you'd just have to re-implement this stuff, wouldn't you? Or what am I missing? Tricks like appending ".jpg" to the url seem a little hack-ish to me. That feels like a parameter. Now what if there are two parameters, how do I know which comes first if someone else wrote it who doesn't use the same style as I do? If I'm querying for an employee, is it clear that I should use employee/110.jpg and not employee.jpg/110 or employee/110/jpg or employee/110/query/jpg, or somethere else?
- ramen 17y agoIndeed. The parameter-passing mechanism is something XML-RPC decides for you, rather than leaving the task of string concatenation (or XML message-building) to you. One might even call this "opinionated".
- generalk 17y agoIt gives you a unified means to specify functions, along with parameters and their types, and gives errors when the requests don't match the definition. With a REST implementation you roll yourself, you'd just have to re-implement this stuff, wouldn't you? Or what am I missing? I see things in the reverse: HTTP and REST give you a way to make requests, specify parameters, indicate errors, authenticate, etc. XML-RPC ignores all of that and makes you re-implement all of those things. Tricks like appending ".jpg" to the url seem a little hack-ish to me. That feels like a parameter. Now what if there are two parameters, how do I know which comes first if someone else wrote it who doesn't use the same style as I do? Those are meant to resemble file extensions, but they can be thought of as parameters. If I'm querying for an employee, is it clear that I should use employee/110.jpg and not employee.jpg/110 or employee/110/jpg or employee/110/query/jpg, or somethere else? It's not standardized, just like XML-RPC isn't. Either way you can read the documentation for your service and it'll tell you. Alternatively, in REST everything has a URI. This has two interesting properties: 1. You can always access a resource by its unique URI: http://example/employees/110.jpg http://example/employees/110.jpg 2. As seen on the WWW: hypermedia links. If you request /employees.json, for instance, I can provide a structure like: {name: "John Employee", related: { image: "http://example/employees/110.jpg", performance_review: "http://example/employees/110/review" } } Which means that with your response you can easily request those URIs and get the resources. Those URIs should never change (as mentioned), but HTTP provides for redirection if they do. XML-RPC does not provide for this at all. (edited for formatting)
- jcapote 17y agoXML-RPC is useless now that BERT-RPC exists, imo.
- ramen 17y agoXML-RPC is still supported by more languages, and doesn't require third-party libraries for Python or Ruby users. But this looks interesting, thanks for mentioning it.
- DougWebb 17y agoA lot of questions are of the form "XML-RPC does X, but it isn't clear how to do X in REST", and the answer to most of those questions should be "You wouldn't design the system to do X when taking the REST approach." Think of it this way: XML-RPC is structured programming, which is all about the subroutines you call, the data you pass to them, and the data you get back. REST is object oriented programming, which is all about the data and the methods you use to interact with the data. In REST, a type of resource is like a class, a specific resource is like an object, and all objects have some/all of the same basic methods: OPTIONS, HEAD, GET, PUT, POST, DELETE. These methods always have the same purposes: OPTIONS: which methods does this resource support HEAD: what is this resources metadata GET: get a representation of the resource PUT: store a new representation of the resource POST: create a new resource and return its URI DELETE: get rid of the resource The HTTP standard defines the responses to all of these methods, except for the specific representations. The defined responses include the status codes to return, the resource metadata (various HTTP headers), and how to specify the Content-Type header which identifies the representation being returned. The standard also specifies how the client should tell the service which representations it knows how to handle, in order to negotiate and find a useful content-type. Where REST services differ are: 1) What resources are available 2) What are the representations for each resource 3) What additional arguments are supported for each method and representation. (Query parameters for HEAD and GET, content body for POST and PUT.) Another typical pattern for REST services is that, for every resource type, there is also a collection resource. To create a new resource, you PUT to a specific resource URI, or you POST to the container. Which you choose to implement as a service designer depends upon who's responsible for deciding the URI for the new resource; if the client decides use PUT, and if the service decides use POST. One commenter asks (paraphrasing) "How do I use REST to call a function and pass an array as the third argument, and get back a sensible error if I pass a hash instead?". My response is that you probably wouldn't be doing something like that with a REST service. It's difficult to be more specific without a concrete example, but right from the top I'd say you're not calling functions in REST, and you need to invert your thinking in order to switch between XML-RPC mode and REST mode. (Similar to the way you can never really work well with OOP as long as you're thinking in terms of subroutines rather than classes and objects.)
- 17y ago
- akeefer 17y agoI'm not much of a fan of the bloat that SOAP has acquired, but to me the point of something XML-based isn't so much the transport side but instead the API-publishing side. The point of a WSDL or similar descriptor is to define what's available: what methods you can call, what types of data they take, and what sorts of data they return. Generally, you can query the server for the WSDL in addition to actually executing the calls. To me that's the primary advantage, and the reason why a lot of clients prefer SOAP (or some other XML-RPC approach): it's because it provides a clear, published API that you can hand off to someone and have them program against, and there are tools for basically every language that can interpret that API. For statically-typed languages, those tools can also help make sure that your calls are at least syntactically valid, i.e. you're not making calls to methods that don't exist, or passing Strings in for integer parameters, or referencing fields off the result object that aren't there, etc. That might not seem like a big deal, but when you're calling a totally unfamiliar API, it can help you get up to speed much faster, and when you have clients that rely on that API, it really helps everyone's peace of mind when they can be 100% sure that API isn't changing on them. I'm not aware of an similar, standardized, machine-readable equivalent for REST service documentation, though I'd certainly love to know about it if there is one.
- blasdel 17y agoTrue REST abhors the idea of separate "standardized, machine-readable documentation" like WSDL. The biggest point of REST is that Hypertext Is The Engine Of Application State -- but unfortunately most people focus on bullshit naming conventions that are largely False REST. Every response should contain hyperlinks to other resources, where the structure/metadata around it indicates what's on the other end. It should still be self-describing even if the URL is completely opaque -- "nice URLs" do not make you RESTful. You should never need an "endpoint" or any documentation at all, whether machine or human-readable. I should be able to explore your whole API just using HTTP. Ideally you'd use the exact same URLs for your API and browser-human interfaces, using the Accept: header to get different representations of the response. Almost everybody fucks this up, and just uses 'meaningful' URLs that you're expected to build yourself, and lots of sassy human documentation to tell you what the constants are.
- tlrobinson 17y agoFirst let me say I'm not arguing for XML-RPC. See my actual question at the bottom. One nice thing about protocols like XML-RPC is they're well defined, unlike the somewhat abstract idea of "REST", which leaves a lot of room for interpretation. You end up with lots of different REST API styles created by people of various levels of competence and understanding of what REST is. It makes it harder to create client libraries that handle the mundane aspects of communicating with these APIs. Projects like httparty and rest-client do help somewhat, but they end up injecting their opinion of what the "correct" way to do REST is. So my question is: has there been any effort to codify REST API best practices into a lightweight REST "protocol", such that it would be easy to write generic client libraries, yet still obey the principles of REST?
- sandGorgon 17y agoActiveResource ? http://api.rubyonrails.org/files/vendor/rails/activeresource/README.html http://api.rubyonrails.org/files/vendor/rails/activeresource...
- regularfry 17y agoIt's shameless-plug-time, I'm afraid: http://github.com/regularfry/xmlrpc_annotations A library I knocked together a while ago to generate C# interface files for an XMLRPC service by annotating the Ruby source. It could be extended to other languages, but I never bothered. I used it to serve the interface file directly from http://example.com/service/Foo.cs http://example.com/service/Foo.cs. Works nicely for what it does. To bring this comment lurching somewhat closer to the topic at hand, would this be a feasible approach for RESTful interfaces?