Live data from Hacker News

How Not to write a "REST" API

api.sharefile.com

41–50 of 117 posts

Re: How Not to write a "REST" API

#41
post #11
post #6

Earlier quoted context omitted.

I was going to mention this. If this documentation completely removed the word 'REST' would we have cringed as bad?

Probably not, but after seeing how nice REST API's can be with sensible url mappings, HATEOAS, HTTP methods as verbs, etc. it's almost insulting for sharefile to call it RESTful (presumably because it can return JSON?). Off the top of my head: - API method urls are all the same .aspx, regardless of method used - All calls are sent as GET (ignoring the whole point of HTTP methods in REST) - No HTTP method codes as res…

"API method urls are all the same .aspx, regardless of method used"

Isn't it more the fact that they spend all of their efforts documenting the URI structure and very little on the media types used - which is very unRESTful.

Re: How Not to write a "REST" API

#42

Earlier quoted context omitted.

The query string and headers ARE encrypted in https. And forms auth, that's just a post and a cookie. You can't require API clients to support cookies.

But, and excuse me if I'm wrong on this I'm looking for clarification, you should be forcing API clients to sign their requests with some sort of token - which might as well be a cookie. The difference being that a browser keeps track of the cookies for you, and any other client will have to keep track of any auth info itself (in a sqlite DB, xml file, held in memory, etc)

It's been a while since I've used AWS, but I consider their API to be the gold standard. IIRC, they have you concatenate a few fields plus a message length, and sign it with your secret key, and this signature is your authentication and anti-tamper mechanism.

Re: How Not to write a "REST" API

#43
post #12

What else is flawed with this API? I'd be nice to have a "Dos and Don'ts in REST API design", with the Don'ts exemplified with Sharefile's API.

From a quick glance:

- Doesn't use HTTP verbs (GET, PUT, POST, DELETE) to retrieve, modify, create and remove objects.

- Doesn't use a restful url path to action on (ie. GET /users/#{user_id} to get a specific user by id, POST /users to create a new user).

- Doesn't use HTTP codes to return results (ie. HTTP 200 for normal operations, 201 for created, 40x for error conditions).

Re: How Not to write a "REST" API

#44

Earlier quoted context omitted.

It's not compliant with the HTTP standard.

In what way is it not compliant?

It's not 'compliancy' as much as they're reinventing the wheel.

REST was born out of a philosophy that the HTTP protocol already solved much of what you wanted to do. HTTP not only solved this, but solved this a long time ago and with 'great success' (aka The Interwebs ;-)

- Authentication mechanism

- Operations (CRUD) -> GET, PUT, POST, DELETE, ...

- Caching -> Use HTTP caching mechanisms...

- Resources -> URL's

- Formats -> mime-types + use a HTTP Accept: header

- ...

They reinvent the wheel on many of the bullet points above: custom operations, custom format handling, custom authentication mechanisms, ... That's why this really is one of the worst implementation of an 'RESTful' API

Re: How Not to write a "REST" API

#45
post #12

What else is flawed with this API? I'd be nice to have a "Dos and Don'ts in REST API design", with the Don'ts exemplified with Sharefile's API.

I'd like to know the same thing. Aside from everyone complaining that they used the term RESTful wrong, is there anything really wrong? It authenticates securely over HTTPS so I am confused what is wrong. Saying it's not complaint I don't really follow either. Thanks for any help.

I guess it's also a matter of taste. In any case, my taste is this:

RESTful APIs usually represent CRUD operations, each of these letter can be beautifully mapped to request types: - CREATE -> POST - READ -> GET - UPDATE -> PUT - DELETE -> DELETE

Second point: {error: false, value: actual_data} If we have an error variable, what is the HTTP error code then good for? Normal Web Servers use the HTTP error codes for a reason. Besides using standard webframework a json containing only "actual_data" means less code, less errors and so forth...

Third point: URLs should represent the hierarchy: GET /users/43/bookmarks/32442?... is much more beautiful and straight-forward to work with than /api_handler.exe?user_id=43&bookmark_id=32442&operation=get...

Regarding authentication: use a secret API key, that's simple and secure. Everybody does that, from small services to multi million user services like facebook.

As a hint: read the dissertation of Roy Fielding who "invented" REST. In my opinion REST means to exploit HTTP as far as possible instead of using any custom conventions.

Re: How Not to write a "REST" API

#46
post #5

Looks like an RPC-style API with multiple endpoints + custom authentication scheme.

This reminds me of Shu-Ha-Ri (Cockburn from way back - Agile as Coop):

Shu - you don't know what you're doing (people here asking for help);

Ha - you closely follow the rules (people here complaining);

Ri - you understand the topic sufficiently to adapt and respond as necessary (people for whom this is really not a big deal).

[Actually, now that I read the Wikipedia page for that, it's not quite right - apologies to any martial arts people out there http://en.wikipedia.org/wiki/Shuhari]

Re: How Not to write a "REST" API

#47
post #11
post #6

Earlier quoted context omitted.

I was going to mention this. If this documentation completely removed the word 'REST' would we have cringed as bad?

Probably not, but after seeing how nice REST API's can be with sensible url mappings, HATEOAS, HTTP methods as verbs, etc. it's almost insulting for sharefile to call it RESTful (presumably because it can return JSON?). Off the top of my head: - API method urls are all the same .aspx, regardless of method used - All calls are sent as GET (ignoring the whole point of HTTP methods in REST) - No HTTP method codes as res…

I'm with you on just knowing we can do so much better. Some of the RESTful HATEOS based APIs coming out are simply beautiful. However,

    - API method urls are all the same .aspx, regardless
    of method used
Extensions are meaningless. That is why we have Accept/Content-type headers. The HTTP spec even explicitly says to not use extensions to relay content information between client and server, from what I recall.

    - All calls are sent as GET (ignoring the whole point
    of HTTP methods in REST)
I haven't read Fielding's dissertation in a while, but using the "Coles Notes" version from Wikipedia, I do not actually see using the verbs a requirement for REST. I do not recall REST even requiring HTTP. You can use any protocol you want, so long as it conforms to the principles.

RESTful, on the other hand, does specify the use of HTTP verbs, but the site in question makes no mention of being RESTful.

By not using the proper verbs, the site does appear to violate the caching rules of REST though, I'll give you that.

    - Custom authentication putting credentials in URL
    or in headers (neither of which are encrypted over
    https)
The entire https payload is encrypted, headers and all. REST says nothing about how authentication should be implemented.

    - Return format is done with get arguments instead
    of HTTP content negotiation in headers (not so bad)
This falls under the same as using extensions. Though I will agree with you that it is a reasonable compromise in some cases, such as using a browser where you can't reasonably set your own headers.

Re: How Not to write a "REST" API

#48

As @artanis0 (kind of) mentioned, it'd be great to see a HN post sometime soon called "How to write a good 'REST' API". Or even just some links to good tutorials that could get me (and others) started? I've recently built a DB driven site that could possibly be extended with an API, and it's a good chance to learn something with a purpose behind it!

It's pretty straight forward, just do the following:

- Use HTTP verbs: GET to retrieve one or more objects, POST to create a new object, PUT to update an existing object, DELETE to remove an object.

- Address objects by collection and by individual object: /users/#{user_id} is a specific user you can PUT, GET or DELETE. /users is where you POST to in order to create a new user.

- Use HTTP codes to return the result back to the client (ie HTTP 200 when you get an object, 201 when you successfully POST an object, 404 when you try to GET/UPDATE/DELETE an object that doesn't exist).

- I find it good form to return objects in JSON with the type of object at the top of the data structure, ie {:users => [ #array of users here ]} or {:user => { #single user }}

- Use OAuth or some sort of token system for authenticating the calls, don't use HTTP Auth.

You can get pretty anal about things but if you follow the above you'll have a cleaner API than 90% of the API's out there.

Re: How Not to write a "REST" API

#49
post #12

What else is flawed with this API? I'd be nice to have a "Dos and Don'ts in REST API design", with the Don'ts exemplified with Sharefile's API.

There are a few comments in this post that touch on the flaws of this API. Here's the gist:

1. HTTP methods are improperly used. The documentation states "All API calls should be sent as a GET HTTP request". GET is used to retrieve resources, and should be cacheable. It should NEVER change the state of a resource. Yet we see in that it's used to delete, create, and modify resources! Examples:

GET https://subdomain.sharefile.com/rest/folder.aspx?op=create...

GET https://subdomain.sharefile.com/rest/file.aspx?op=delete

These should be as follows:

POST https://subdomain.sharefile.com/rest/folder.aspx

DELETE https://subdomain.sharefile.com/rest/file.aspx

HTTP verbs have specific semantics that allow for intelligent, scalable architecture.

2. Individual resources are not identified by an unchangeable URI. Let's say I want a folder:

GET https://subdomain.sharefile.com/rest/folder.aspx?op=get&...

Nope. This is more RESTful:

GET https://subdomain.sharefile.com/rest/folder/123

Two things to note: 1) no 'aspx' bullshit, that's implementation and shouldn't be visible to the user, and 2) the ID is in the URI itself as opposed to the params. URIs should seldom, if ever, change. Parameter names may change, URIs shouldn't.

3. Violation of content type retrieval. Let's say I want a folder as XML:

GET https://subdomain.sharefile.com/rest/folder.aspx?op=get&...

Wrong. This is the request I should be sending as a curl:

curl https://subdomain.sharefile.com/rest/folder/123 -H 'Accept: text/xml'

Note that I'm using the Accept header. This allows for flexibility in accessing my resource. With any luck, the server will give me an XML file, and its content type should be "text/vnd.sharefile+xml" (vendor specific content types are best).

4. No link relations in the body. I'm mostly assuming this because I haven't seen sample response bodies, but almost no one does this even though is a crucial aspect of a RESTful service. RESTful services describe the relationship between resources. Suppose I have an ordered collection of files. When retrieving a file, it should describe its relationship in this ordered collection. This is done either via the LINK header, or some sort of scheme in your response body (e.g. JSON Schema describes 'link' attributes).

A pretty good RESTful API is Github's (see http://developer.github.com/). If you'd like to learn more, I highly recommend "REST in Practice" by Webber, et al (http://www.amazon.ca/REST-Practice-Hypermedia-Systems-Archit...).

Re: How Not to write a "REST" API

#50
post #43
post #12

What else is flawed with this API? I'd be nice to have a "Dos and Don'ts in REST API design", with the Don'ts exemplified with Sharefile's API.

From a quick glance: - Doesn't use HTTP verbs (GET, PUT, POST, DELETE) to retrieve, modify, create and remove objects. - Doesn't use a restful url path to action on (ie. GET /users/#{user_id} to get a specific user by id, POST /users to create a new user). - Doesn't use HTTP codes to return results (ie. HTTP 200 for normal operations, 201 for created, 40x for error conditions).

> - Doesn't use a restful url path to action on (ie. GET /users/#{user_id} to get a specific user by id, POST /users to create a new user).

That is specifically one thing which does not apply and is completely irrelevant. Good-looking URLs have nothing to do with REST.

The rest, yes.

Post reply on HN