Live data from Hacker News

When REST isn't Good Enough

braintreepayments.com

31–40 of 94 posts

Re: When REST isn't Good Enough

#31

We (Zapier) are in a particularly good place to comment on this. We have implemented about 70 very diverse web APIs in-house. Early on, we used client libraries because they were easy and convenient. That decision bit us, hard. (Most) client libraries are un-maintained, opaque, and difficult to extend. We spent many months ripping every client library out down to the raw requests. We are in a unique position because…

Can you respond directly to some of the points raised in the article? For example, ensuring SSL certs are validated?

The big problem I see is that SSL requires an unbroken chain of trust all the way along. If I have client-side code connecting to my server, which is then connecting to a third party server, all of those links have to be secured. As someone else pointed out, it`s nice to make your payment processing secure, but at some point the developer also has to step up and ensure their half of the bargain is upheld. If I`m sending credit card details to my backend over HTTP for some reason, no API in the world will stop me.

Even looking at Stripe; they provide a JS library so you can do client-side encryption. However, if you include that JS library on an incorrectly SSLed page, a malicious party could replace it without you knowing. Even with extensive hand-holding, if a user is going to implement SSL badly, there will be security risks.

The only sure-fire solution is for the developers of SSL libraries to come together and implement sane default options, and clear documentation of how not to do things. Looking at the docs for OpenSSL, it`s impossible to easily discern what counts as a sane configuration. The same problem propagates itself into language-specific libraries, where the dev wasn`t quite sure what options to tick to begin with. And so it goes.

Re: When REST isn't Good Enough

#32
post #4

Braintree have made an interesting choice in keeping their REST API private and requiring customers use their client libraries. I think they could both have client libraries that they promote as well as a public REST API. Breaking down their reasons: Security - agree with them on this, the more they can help their users make their systems secure the better. Not sure if it should preclude a public REST API but certain…

I'm a developer at Braintree. The challenge with maintaining backwards compatibility on the server side is handling the wide variety of possible inputs into the system. It's hard to write tests that account for all of them.

I've seen a couple of cases where backwards compatibility can be broken in unexpected ways. For one application that we built at Braintree, we had a client that was sending us an application/x-www-form-urlencoded POST body without the Content-Type request header. We upgraded the version of Rails that this app was using, and it broke that integration because Rails made a change where it wouldn't parse the POST body without the Content-Type header. Unfortunately, we didn't have any test cases in our test suite that made POSTs without a Content-Type. We were able to identify the issue and resolve it quickly, but it was a surprising bug. With client libraries, we can test every version against the upgraded app and know that all clients will continue to work.

Are there interesting request profiling techniques that can be executed on production traffic to analyze requests? I think the challenging part of backwards compatibility is making sure unintentional use cases, that were never intended to be supported, continue to work.

Re: When REST isn't Good Enough

#33
post #7
post #5

I don't like REST. Making a call to a server should be like calling a function anywhere else - you have your parameters and return value. In REST the parameters are spread over 3 places, the action, the url and the post parameters themselves. It's a much better design to combine all your parameters in one place and keep things simple, for example - REST version: UPDATE /course/324234 { description: "This is a level 1…

If your course has 20 member variables, now you have 20 update methods? If you want to update multiple, the client then needs to do multiple round-trip calls to your API which is time-consuming: if it's a 350ms round-trip per call, updating all 20 fields takes 7 seconds. And unless you go out of your way to offer per-object locking (which over a stateless connection has its own challenges) you prevent users from doin…

Like any other programming language if you need to update multiple fields, you pass multiple parameters to the function. The URL should be equivalent to namespace/class/method while the parameters are just that - parameters you can pass in JSON format.

Re: When REST isn't Good Enough

#34
post #28
post #27

Earlier quoted context omitted.

I'm not saying how the parameters or return values should be formatted other than the fact they're in JSON format. JSON-RPC requires you to conform to their specifications.

APIs that ignore the realities of distributed computing and that each have different special-snowflake wire formats requiring tedious documentation: the worst of both worlds.

I'm not arguing against implementing an RPC if that's what you need. My original post describes a super set of JSON-RPC.

Re: When REST isn't Good Enough

#35
post #29
post #13

Earlier quoted context omitted.

The REST version makes it clear that you are dealing with operations on a resource. The URL identifies a thing in a consistent way, while the method and corresponding data allow you to manipulate it. The biggest benefit comes when building a cache architecture. RESTful API's (when properly implemented) come with built-in assumptions about idempotency. You end up in a place where you can easily cache GET requests whil…

Just because something is GET doesn't mean it can be cached. It's not consistent, and every API call needs to be evaluated individually. The thing with REST is that it treats all functions as a variant of a CRUD operation, while functions may do more than just CRUD or a combination of CRUD operations in a single API call. Imagine if all your javascript functions had to be prefixed with GET/UPDATE/DELETE/etc.. you wou…

GET requests, by definition, should have no side-effects. Which makes them cacheable. Many browsers cache GET requests by default unless cache-control tells them not to.

You can most definitely write a GET request that contains side-effects, but that's because you're doing it wrong (tm).

Imagine if your function names had data in the call path MyCourse.32423.Delete(); that doesn't look very good does it? 32423 would look alot better inside Delete().

That's not data, that's an object. "MyCourse.32423" is the actual resource. It would actually look something more like:

MyCourse32423.Delete();

Which seems pretty reasonable to me if we're trying to map this into programming language semantics (which I'm not even sure we should be doing).

Re: When REST isn't Good Enough

#36
post #33
post #7

Earlier quoted context omitted.

If your course has 20 member variables, now you have 20 update methods? If you want to update multiple, the client then needs to do multiple round-trip calls to your API which is time-consuming: if it's a 350ms round-trip per call, updating all 20 fields takes 7 seconds. And unless you go out of your way to offer per-object locking (which over a stateless connection has its own challenges) you prevent users from doin…

Like any other programming language if you need to update multiple fields, you pass multiple parameters to the function. The URL should be equivalent to namespace/class/method while the parameters are just that - parameters you can pass in JSON format.

You're putting the burden of learning implementation details of your system onto your customers. That won't be comfortable for either them or you. Should you need to deprecate a method you'll never be able to remove it. So be prepared to write a lot of { "Error": "ErrorCodeThatOnlyMakesSenseInTheContextOfThisAPI", "Description": "DEPRECATED" }

Re: When REST isn't Good Enough

#37

Earlier quoted context omitted.

Can you respond directly to some of the points raised in the article? For example, ensuring SSL certs are validated?

Sure. I'll start with this: as far as client libraries go, Braintree is doing it right. Because it's the only thing they support, they are incentivized to make sure it is feature complete and bug free. SSL: It is not the onus of the vendor to ensure people are properly securing requests. I have seen horrendous things done in the name of "security" but it only adds headaches. Fix this at the client level. SSL everywhe…

>SSL: It is not the onus of the vendor to ensure people are properly securing requests.

Two responses: first, Braintree customers may appreciate knowing that Braintree provides a safer implementation than whatever the (third)contractor that they hired to build thier web app might throw together.

Second, fraud does directly impact their business, regardless of the entry point used by the attacker. Even if they don't get stuck for the money directly, they are going to lose time talking to customers and helping with investigations.

They don't have to do either, but they may find that they can make some types of customer relationships profitable that would not be for a competing business that doesn't do as much hand-holding.

Re: When REST isn't Good Enough

#38
post #35
post #29

Earlier quoted context omitted.

Just because something is GET doesn't mean it can be cached. It's not consistent, and every API call needs to be evaluated individually. The thing with REST is that it treats all functions as a variant of a CRUD operation, while functions may do more than just CRUD or a combination of CRUD operations in a single API call. Imagine if all your javascript functions had to be prefixed with GET/UPDATE/DELETE/etc.. you wou…

GET requests, by definition, should have no side-effects. Which makes them cacheable. Many browsers cache GET requests by default unless cache-control tells them not to. You can most definitely write a GET request that contains side-effects, but that's because you're doing it wrong (tm). Imagine if your function names had data in the call path MyCourse.32423.Delete(); that doesn't look very good does it? 32423 would…

I cringe a little bit whenever someone tries to present caching as simple or straightforward.

Re: When REST isn't Good Enough

#40

We (Zapier) are in a particularly good place to comment on this. We have implemented about 70 very diverse web APIs in-house. Early on, we used client libraries because they were easy and convenient. That decision bit us, hard. (Most) client libraries are un-maintained, opaque, and difficult to extend. We spent many months ripping every client library out down to the raw requests. We are in a unique position because…

What about some sort of client library generator, similar to how .NET languages can generate code from other .NET WSDLs?
Post reply on HN